提交 f71eaf68 编写于 作者: L Linus Torvalds

Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: (41 commits)
  hwmon: (adt7475) Add VID support for the ADT7476
  hwmon: (adt7475) Add an entry in MAINTAINERS
  hwmon: (adt7475) Add support for the ADT7476
  hwmon: (adt7475) Voltage attenuators can be bypassed
  hwmon: (adt7475) Print device information on probe
  hwmon: (adt7475) Handle alternative pin functions
  hwmon: (adt7475) Move sysfs files removal to a separate function
  hwmon: (adt7475) Add support for the ADT7490
  hwmon: (adt7475) Improve device detection
  hwmon: (adt7475) Add missing static marker
  hwmon: (adt7475) Rework voltage inputs handling
  hwmon: (adt7475) Implement pwm_use_point2_pwm_at_crit
  hwmon: (adt7475) New documentation
  hwmon: (adt7475) Add support for the ADT7473
  hwmon: (f71882fg) Add support for the f71889fg (version 2)
  hwmon: (f71882fg) Fix sysfs file removal
  hwmon: (f71882fg) Cleanup sysfs attr creation 2/2
  hwmon: (f71882fg) Cleanup sysfs attr creation 1/2
  hwmon: (thmc50) Stop using I2C_CLIENT_MODULE_PARM
  hwmon: Add Freescale MC13783 ADC driver
  ...
...@@ -483,3 +483,10 @@ Why: With the recent innovations in CPU hardware acceleration technologies ...@@ -483,3 +483,10 @@ Why: With the recent innovations in CPU hardware acceleration technologies
Who: Alok N Kataria <akataria@vmware.com> Who: Alok N Kataria <akataria@vmware.com>
---------------------------- ----------------------------
What: adt7473 hardware monitoring driver
When: February 2010
Why: Obsoleted by the adt7475 driver.
Who: Jean Delvare <khali@linux-fr.org>
---------------------------
...@@ -9,6 +9,8 @@ Supported chips: ...@@ -9,6 +9,8 @@ Supported chips:
Author: Darrick J. Wong Author: Darrick J. Wong
This driver is depreacted, please use the adt7475 driver instead.
Description Description
----------- -----------
......
This describes the interface for the ADT7475 driver: Kernel driver adt7475
=====================
(there are 4 fans, numbered fan1 to fan4):
Supported chips:
fanX_input Read the current speed of the fan (in RPMs) * Analog Devices ADT7473
fanX_min Read/write the minimum speed of the fan. Dropping Prefix: 'adt7473'
below this sets an alarm. Addresses scanned: I2C 0x2C, 0x2D, 0x2E
Datasheet: Publicly available at the On Semiconductors website
(there are three PWMs, numbered pwm1 to pwm3): * Analog Devices ADT7475
Prefix: 'adt7475'
pwmX Read/write the current duty cycle of the PWM. Writes Addresses scanned: I2C 0x2E
only have effect when auto mode is turned off (see Datasheet: Publicly available at the On Semiconductors website
below). Range is 0 - 255. * Analog Devices ADT7476
Prefix: 'adt7476'
pwmX_enable Fan speed control method: Addresses scanned: I2C 0x2C, 0x2D, 0x2E
Datasheet: Publicly available at the On Semiconductors website
0 - No control (fan at full speed) * Analog Devices ADT7490
1 - Manual fan speed control (using pwm[1-*]) Prefix: 'adt7490'
2 - Automatic fan speed control Addresses scanned: I2C 0x2C, 0x2D, 0x2E
Datasheet: Publicly available at the On Semiconductors website
pwmX_auto_channels_temp Select which channels affect this PWM
Authors:
1 - TEMP1 controls PWM Jordan Crouse
2 - TEMP2 controls PWM Hans de Goede
4 - TEMP3 controls PWM Darrick J. Wong (documentation)
6 - TEMP2 and TEMP3 control PWM Jean Delvare
7 - All three inputs control PWM
pwmX_freq Read/write the PWM frequency in Hz. The number Description
should be one of the following: -----------
11 Hz This driver implements support for the Analog Devices ADT7473, ADT7475,
14 Hz ADT7476 and ADT7490 chip family. The ADT7473 and ADT7475 differ only in
22 Hz minor details. The ADT7476 has additional features, including extra voltage
29 Hz measurement inputs and VID support. The ADT7490 also has additional
35 Hz features, including extra voltage measurement inputs and PECI support. All
44 Hz the supported chips will be collectively designed by the name "ADT747x" in
58 Hz the rest of this document.
88 Hz
The ADT747x uses the 2-wire interface compatible with the SMBus 2.0
pwmX_auto_point1_pwm Read/write the minimum PWM duty cycle in automatic mode specification. Using an analog to digital converter it measures three (3)
temperatures and two (2) or more voltages. It has four (4) 16-bit counters
pwmX_auto_point2_pwm Read/write the maximum PWM duty cycle in automatic mode for measuring fan speed. There are three (3) PWM outputs that can be used
to control fan speed.
(there are three temperature settings numbered temp1 to temp3):
A sophisticated control system for the PWM outputs is designed into the
tempX_input Read the current temperature. The value is in milli ADT747x that allows fan speed to be adjusted automatically based on any of the
degrees of Celsius. three temperature sensors. Each PWM output is individually adjustable and
programmable. Once configured, the ADT747x will adjust the PWM outputs in
tempX_max Read/write the upper temperature limit - exceeding this response to the measured temperatures without further host intervention.
will cause an alarm. This feature can also be disabled for manual control of the PWM's.
tempX_min Read/write the lower temperature limit - exceeding this Each of the measured inputs (voltage, temperature, fan speed) has
will cause an alarm. corresponding high/low limit values. The ADT747x will signal an ALARM if
any measured value exceeds either limit.
tempX_offset Read/write the temperature adjustment offset
The ADT747x samples all inputs continuously. The driver will not read
tempX_crit Read/write the THERM limit for remote1. the registers more often than once every other second. Further,
configuration data is only read once per minute.
tempX_crit_hyst Set the temperature value below crit where the
fans will stay on - this helps drive the temperature Chip Differences Summary
low enough so it doesn't stay near the edge and ------------------------
cause THERM to keep tripping.
ADT7473:
tempX_auto_point1_temp Read/write the minimum temperature where the fans will * 2 voltage inputs
turn on in automatic mode. * system acoustics optimizations (not implemented)
tempX_auto_point2_temp Read/write the maximum temperature over which the fans ADT7475:
will run in automatic mode. tempX_auto_point1_temp * 2 voltage inputs
and tempX_auto_point2_temp together define the
range of automatic control. ADT7476:
* 5 voltage inputs
tempX_alarm Read a 1 if the max/min alarm is set * VID support
tempX_fault Read a 1 if either temp1 or temp3 diode has a fault
ADT7490:
(There are two voltage settings, in1 and in2): * 6 voltage inputs
* 1 Imon input (not implemented)
inX_input Read the current voltage on VCC. Value is in * PECI support (not implemented)
millivolts. * 2 GPIO pins (not implemented)
* system acoustics optimizations (not implemented)
inX_min read/write the minimum voltage limit.
Dropping below this causes an alarm. Special Features
----------------
inX_max read/write the maximum voltage limit.
Exceeding this causes an alarm. The ADT747x has a 10-bit ADC and can therefore measure temperatures
with a resolution of 0.25 degree Celsius. Temperature readings can be
inX_alarm Read a 1 if the max/min alarm is set. configured either for two's complement format or "Offset 64" format,
wherein 64 is subtracted from the raw value to get the temperature value.
The datasheet is very detailed and describes a procedure for determining
an optimal configuration for the automatic PWM control.
Fan Speed Control
-----------------
The driver exposes two trip points per PWM channel.
point1: Set the PWM speed at the lower temperature bound
point2: Set the PWM speed at the higher temperature bound
The ADT747x will scale the PWM linearly between the lower and higher PWM
speed when the temperature is between the two temperature boundaries.
Temperature boundaries are associated to temperature channels rather than
PWM outputs, and a given PWM output can be controlled by several temperature
channels. As a result, the ADT747x may compute more than one PWM value
for a channel at a given time, in which case the maximum value (fastest
fan speed) is applied. PWM values range from 0 (off) to 255 (full speed).
Fan speed may be set to maximum when the temperature sensor associated with
the PWM control exceeds temp#_max.
Notes
-----
The nVidia binary driver presents an ADT7473 chip via an on-card i2c bus.
Unfortunately, they fail to set the i2c adapter class, so this driver may
fail to find the chip until the nvidia driver is patched.
...@@ -14,6 +14,10 @@ Supported chips: ...@@ -14,6 +14,10 @@ Supported chips:
Prefix: 'f71882fg' Prefix: 'f71882fg'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
Datasheet: Available from the Fintek website Datasheet: Available from the Fintek website
* Fintek F71889FG
Prefix: 'f71889fg'
Addresses scanned: none, address read from Super I/O config space
Datasheet: Should become available on the Fintek website soon
* Fintek F8000 * Fintek F8000
Prefix: 'f8000' Prefix: 'f8000'
Addresses scanned: none, address read from Super I/O config space Addresses scanned: none, address read from Super I/O config space
...@@ -51,6 +55,12 @@ supported. The right one to use depends on external circuitry on the ...@@ -51,6 +55,12 @@ supported. The right one to use depends on external circuitry on the
motherboard, so the driver assumes that the BIOS set the method motherboard, so the driver assumes that the BIOS set the method
properly. properly.
Note that the lowest numbered temperature zone trip point corresponds to
to the border between the highest and one but highest temperature zones, and
vica versa. So the temperature zone trip points 1-4 (or 1-2) go from high temp
to low temp! This is how things are implemented in the IC, and the driver
mimicks this.
There are 2 modes to specify the speed of the fan, PWM duty cycle (or DC There are 2 modes to specify the speed of the fan, PWM duty cycle (or DC
voltage) mode, where 0-100% duty cycle (0-100% of 12V) is specified. And RPM voltage) mode, where 0-100% duty cycle (0-100% of 12V) is specified. And RPM
mode where the actual RPM of the fan (as measured) is controlled and the speed mode where the actual RPM of the fan (as measured) is controlled and the speed
......
...@@ -86,7 +86,6 @@ The IT8712F and IT8716F additionally feature VID inputs, used to report ...@@ -86,7 +86,6 @@ The IT8712F and IT8716F additionally feature VID inputs, used to report
the Vcore voltage of the processor. The early IT8712F have 5 VID pins, the Vcore voltage of the processor. The early IT8712F have 5 VID pins,
the IT8716F and late IT8712F have 6. They are shared with other functions the IT8716F and late IT8712F have 6. They are shared with other functions
though, so the functionality may not be available on a given system. though, so the functionality may not be available on a given system.
The driver dumbly assume it is there.
The IT8718F and IT8720F also features VID inputs (up to 8 pins) but the value The IT8718F and IT8720F also features VID inputs (up to 8 pins) but the value
is stored in the Super-I/O configuration space. Due to technical limitations, is stored in the Super-I/O configuration space. Due to technical limitations,
......
Kernel driver mc13783-adc
=========================
Supported chips:
* Freescale Atlas MC13783
Prefix: 'mc13783_adc'
Datasheet: http://www.freescale.com/files/rf_if/doc/data_sheet/MC13783.pdf?fsrch=1
Authors:
Sascha Hauer <s.hauer@pengutronix.de>
Luotao Fu <l.fu@pengutronix.de>
Description
-----------
The Freescale MC13783 is a Power Management and Audio Circuit. Among
other things it contains a 10-bit A/D converter. The converter has 16
channels which can be used in different modes.
The A/D converter has a resolution of 2.25mV. Channels 0-4 have
a dedicated meaning with chip internal scaling applied. Channels 5-7
can be used as general purpose inputs or alternatively in a dedicated
mode. Channels 12-15 are occupied by the touchscreen if it's active.
Currently the driver only supports channels 2 and 5-15 with no alternative
modes for channels 5-7.
See this table for the meaning of the different channels and their chip
internal scaling:
Channel Signal Input Range Scaling
-------------------------------------------------------------------------------
0 Battery Voltage (BATT) 2.50 - 4.65V -2.40V
1 Battery Current (BATT - BATTISNS) -50 - 50 mV x20
2 Application Supply (BP) 2.50 - 4.65V -2.40V
3 Charger Voltage (CHRGRAW) 0 - 10V / /5
0 - 20V /10
4 Charger Current (CHRGISNSP-CHRGISNSN) -0.25V - 0.25V x4
5 General Purpose ADIN5 / Battery Pack Thermistor 0 - 2.30V No
6 General Purpose ADIN6 / Backup Voltage (LICELL) 0 - 2.30V / No /
1.50 - 3.50V -1.20V
7 General Purpose ADIN7 / UID / Die Temperature 0 - 2.30V / No /
0 - 2.55V / x0.9 / No
8 General Purpose ADIN8 0 - 2.30V No
9 General Purpose ADIN9 0 - 2.30V No
10 General Purpose ADIN10 0 - 2.30V No
11 General Purpose ADIN11 0 - 2.30V No
12 General Purpose TSX1 / Touchscreen X-plate 1 0 - 2.30V No
13 General Purpose TSX2 / Touchscreen X-plate 2 0 - 2.30V No
14 General Purpose TSY1 / Touchscreen Y-plate 1 0 - 2.30V No
15 General Purpose TSY2 / Touchscreen Y-plate 2 0 - 2.30V No
...@@ -225,8 +225,6 @@ pwm[1-*]_auto_point[1-*]_temp_hyst ...@@ -225,8 +225,6 @@ pwm[1-*]_auto_point[1-*]_temp_hyst
to PWM output channels. to PWM output channels.
RW RW
OR
temp[1-*]_auto_point[1-*]_pwm temp[1-*]_auto_point[1-*]_pwm
temp[1-*]_auto_point[1-*]_temp temp[1-*]_auto_point[1-*]_temp
temp[1-*]_auto_point[1-*]_temp_hyst temp[1-*]_auto_point[1-*]_temp_hyst
...@@ -235,6 +233,15 @@ temp[1-*]_auto_point[1-*]_temp_hyst ...@@ -235,6 +233,15 @@ temp[1-*]_auto_point[1-*]_temp_hyst
to temperature channels. to temperature channels.
RW RW
There is a third case where trip points are associated to both PWM output
channels and temperature channels: the PWM values are associated to PWM
output channels while the temperature values are associated to temperature
channels. In that case, the result is determined by the mapping between
temperature inputs and PWM outputs. When several temperature inputs are
mapped to a given PWM output, this leads to several candidate PWM values.
The actual result is up to the chip, but in general the highest candidate
value (fastest fan speed) wins.
**************** ****************
* Temperatures * * Temperatures *
......
...@@ -32,8 +32,6 @@ Authors: ...@@ -32,8 +32,6 @@ Authors:
Module Parameters Module Parameters
----------------- -----------------
* force_addr: int
Initialize the ISA address of the sensors
* force_i2c: int * force_i2c: int
Initialize the I2C address of the sensors Initialize the I2C address of the sensors
* init: int * init: int
...@@ -70,3 +68,30 @@ doesn't help, you may just ignore the bogus VID reading with no harm done. ...@@ -70,3 +68,30 @@ doesn't help, you may just ignore the bogus VID reading with no harm done.
For further information on this driver see the w83781d driver documentation. For further information on this driver see the w83781d driver documentation.
[1] http://www.lm-sensors.org/browser/lm-sensors/trunk/doc/vid [1] http://www.lm-sensors.org/browser/lm-sensors/trunk/doc/vid
Forcing the address
-------------------
The driver used to have a module parameter named force_addr, which could
be used to force the base I/O address of the hardware monitoring block.
This was meant as a workaround for mainboards with a broken BIOS. This
module parameter is gone for technical reasons. If you need this feature,
you can obtain the same result by using the isaset tool (part of
lm-sensors) before loading the driver:
# Enter the Super I/O config space
isaset -y -f 0x2e 0x87
isaset -y -f 0x2e 0x87
# Select the hwmon logical device
isaset -y 0x2e 0x2f 0x07 0x0b
# Set the base I/O address (to 0x290 in this example)
isaset -y 0x2e 0x2f 0x60 0x02
isaset -y 0x2e 0x2f 0x61 0x90
# Exit the Super-I/O config space
isaset -y -f 0x2e 0xaa
The above sequence assumes a Super-I/O config space at 0x2e/0x2f, but
0x4e/0x4f is also possible.
...@@ -327,6 +327,13 @@ M: Colin Leroy <colin@colino.net> ...@@ -327,6 +327,13 @@ M: Colin Leroy <colin@colino.net>
S: Maintained S: Maintained
F: drivers/macintosh/therm_adt746x.c F: drivers/macintosh/therm_adt746x.c
ADT7475 HARDWARE MONITOR DRIVER
M: Jean Delvare <khali@linux-fr.org>
L: lm-sensors@lm-sensors.org
S: Maintained
F: Documentation/hwmon/adt7475
F: drivers/hwmon/adt7475.c
ADVANSYS SCSI DRIVER ADVANSYS SCSI DRIVER
M: Matthew Wilcox <matthew@wil.cx> M: Matthew Wilcox <matthew@wil.cx>
L: linux-scsi@vger.kernel.org L: linux-scsi@vger.kernel.org
...@@ -2416,7 +2423,9 @@ HARDWARE MONITORING ...@@ -2416,7 +2423,9 @@ HARDWARE MONITORING
L: lm-sensors@lm-sensors.org L: lm-sensors@lm-sensors.org
W: http://www.lm-sensors.org/ W: http://www.lm-sensors.org/
S: Orphan S: Orphan
F: Documentation/hwmon/
F: drivers/hwmon/ F: drivers/hwmon/
F: include/linux/hwmon*.h
HARDWARE RANDOM NUMBER GENERATOR CORE HARDWARE RANDOM NUMBER GENERATOR CORE
M: Matt Mackall <mpm@selenic.com> M: Matt Mackall <mpm@selenic.com>
...@@ -3312,6 +3321,12 @@ S: Maintained ...@@ -3312,6 +3321,12 @@ S: Maintained
F: Documentation/hwmon/lis3lv02d F: Documentation/hwmon/lis3lv02d
F: drivers/hwmon/lis3lv02d.* F: drivers/hwmon/lis3lv02d.*
LM73 HARDWARE MONITOR DRIVER
M: Guillaume Ligneul <guillaume.ligneul@gmail.com>
L: lm-sensors@lm-sensors.org
S: Maintained
F: drivers/hwmon/lm73.c
LM83 HARDWARE MONITOR DRIVER LM83 HARDWARE MONITOR DRIVER
M: Jean Delvare <khali@linux-fr.org> M: Jean Delvare <khali@linux-fr.org>
L: lm-sensors@lm-sensors.org L: lm-sensors@lm-sensors.org
......
...@@ -191,21 +191,27 @@ config SENSORS_ADT7470 ...@@ -191,21 +191,27 @@ config SENSORS_ADT7470
will be called adt7470. will be called adt7470.
config SENSORS_ADT7473 config SENSORS_ADT7473
tristate "Analog Devices ADT7473" tristate "Analog Devices ADT7473 (DEPRECATED)"
depends on I2C && EXPERIMENTAL depends on I2C && EXPERIMENTAL
select SENSORS_ADT7475
help help
If you say yes here you get support for the Analog Devices If you say yes here you get support for the Analog Devices
ADT7473 temperature monitoring chips. ADT7473 temperature monitoring chips.
This driver is deprecated, you should use the adt7475 driver
instead.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called adt7473. will be called adt7473.
config SENSORS_ADT7475 config SENSORS_ADT7475
tristate "Analog Devices ADT7475" tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490"
depends on I2C && EXPERIMENTAL depends on I2C && EXPERIMENTAL
select HWMON_VID
help help
If you say yes here you get support for the Analog Devices If you say yes here you get support for the Analog Devices
ADT7475 hardware monitoring chips. ADT7473, ADT7475, ADT7476 and ADT7490 hardware monitoring
chips.
This driver can also be build as a module. If so, the module This driver can also be build as a module. If so, the module
will be called adt7475. will be called adt7475.
...@@ -305,12 +311,12 @@ config SENSORS_F71805F ...@@ -305,12 +311,12 @@ config SENSORS_F71805F
will be called f71805f. will be called f71805f.
config SENSORS_F71882FG config SENSORS_F71882FG
tristate "Fintek F71858FG, F71862FG, F71882FG and F8000" tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000"
depends on EXPERIMENTAL depends on EXPERIMENTAL
help help
If you say yes here you get support for hardware monitoring If you say yes here you get support for hardware monitoring
features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG,
and F8000 Super-I/O chips. F71889FG and F8000 Super-I/O chips.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called f71882fg. will be called f71882fg.
...@@ -442,6 +448,15 @@ config SENSORS_LM70 ...@@ -442,6 +448,15 @@ config SENSORS_LM70
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called lm70. will be called lm70.
config SENSORS_LM73
tristate "National Semiconductor LM73"
depends on I2C
help
If you say yes here you get support for National Semiconductor LM73
sensor chips.
This driver can also be built as a module. If so, the module
will be called lm73.
config SENSORS_LM75 config SENSORS_LM75
tristate "National Semiconductor LM75 and compatibles" tristate "National Semiconductor LM75 and compatibles"
depends on I2C depends on I2C
...@@ -841,7 +856,7 @@ config SENSORS_W83781D ...@@ -841,7 +856,7 @@ config SENSORS_W83781D
config SENSORS_W83791D config SENSORS_W83791D
tristate "Winbond W83791D" tristate "Winbond W83791D"
depends on I2C && EXPERIMENTAL depends on I2C
select HWMON_VID select HWMON_VID
help help
If you say yes here you get support for the Winbond W83791D chip. If you say yes here you get support for the Winbond W83791D chip.
...@@ -1008,6 +1023,12 @@ config SENSORS_APPLESMC ...@@ -1008,6 +1023,12 @@ config SENSORS_APPLESMC
Say Y here if you have an applicable laptop and want to experience Say Y here if you have an applicable laptop and want to experience
the awesome power of applesmc. the awesome power of applesmc.
config SENSORS_MC13783_ADC
tristate "Freescale MC13783 ADC"
depends on MFD_MC13783
help
Support for the A/D converter on MC13783 PMIC.
if ACPI if ACPI
comment "ACPI drivers" comment "ACPI drivers"
......
...@@ -57,6 +57,7 @@ obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o ...@@ -57,6 +57,7 @@ obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o obj-$(CONFIG_SENSORS_LIS3_SPI) += lis3lv02d.o lis3lv02d_spi.o
obj-$(CONFIG_SENSORS_LM63) += lm63.o obj-$(CONFIG_SENSORS_LM63) += lm63.o
obj-$(CONFIG_SENSORS_LM70) += lm70.o obj-$(CONFIG_SENSORS_LM70) += lm70.o
obj-$(CONFIG_SENSORS_LM73) += lm73.o
obj-$(CONFIG_SENSORS_LM75) += lm75.o obj-$(CONFIG_SENSORS_LM75) += lm75.o
obj-$(CONFIG_SENSORS_LM77) += lm77.o obj-$(CONFIG_SENSORS_LM77) += lm77.o
obj-$(CONFIG_SENSORS_LM78) += lm78.o obj-$(CONFIG_SENSORS_LM78) += lm78.o
...@@ -73,6 +74,7 @@ obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o ...@@ -73,6 +74,7 @@ obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX1111) += max1111.o
obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o
obj-$(CONFIG_SENSORS_MAX6650) += max6650.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
......
...@@ -288,9 +288,8 @@ static int adm1021_detect(struct i2c_client *client, int kind, ...@@ -288,9 +288,8 @@ static int adm1021_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int i; const char *type_name;
const char *type_name = ""; int conv_rate, status, config, man_id, dev_id;
int conv_rate, status, config;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("adm1021: detect failed, " pr_debug("adm1021: detect failed, "
...@@ -303,62 +302,37 @@ static int adm1021_detect(struct i2c_client *client, int kind, ...@@ -303,62 +302,37 @@ static int adm1021_detect(struct i2c_client *client, int kind,
ADM1021_REG_CONV_RATE_R); ADM1021_REG_CONV_RATE_R);
config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R); config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R);
/* Now, we do the remaining detection. */ /* Check unused bits */
if (kind < 0) { if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) {
if ((status & 0x03) != 0x00 || (config & 0x3F) != 0x00 pr_debug("adm1021: detect failed, chip not detected!\n");
|| (conv_rate & 0xF8) != 0x00) { return -ENODEV;
pr_debug("adm1021: detect failed, "
"chip not detected!\n");
return -ENODEV;
}
} }
/* Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
i = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID); dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
if (i == 0x41)
if ((i2c_smbus_read_byte_data(client,
ADM1021_REG_DEV_ID) & 0xF0) == 0x30)
kind = adm1023;
else
kind = adm1021;
else if (i == 0x49)
kind = thmc10;
else if (i == 0x23)
kind = gl523sm;
else if ((i == 0x4d) &&
(i2c_smbus_read_byte_data(client,
ADM1021_REG_DEV_ID) == 0x01))
kind = max1617a;
else if (i == 0x54)
kind = mc1066;
/* LM84 Mfr ID in a different place, and it has more unused bits */
else if (conv_rate == 0x00
&& (kind == 0 /* skip extra detection */
|| ((config & 0x7F) == 0x00
&& (status & 0xAB) == 0x00)))
kind = lm84;
else
kind = max1617;
}
if (kind == max1617) { if (man_id == 0x4d && dev_id == 0x01)
type_name = "max1617";
} else if (kind == max1617a) {
type_name = "max1617a"; type_name = "max1617a";
} else if (kind == adm1021) { else if (man_id == 0x41) {
type_name = "adm1021"; if ((dev_id & 0xF0) == 0x30)
} else if (kind == adm1023) { type_name = "adm1023";
type_name = "adm1023"; else
} else if (kind == thmc10) { type_name = "adm1021";
} else if (man_id == 0x49)
type_name = "thmc10"; type_name = "thmc10";
} else if (kind == lm84) { else if (man_id == 0x23)
type_name = "lm84";
} else if (kind == gl523sm) {
type_name = "gl523sm"; type_name = "gl523sm";
} else if (kind == mc1066) { else if (man_id == 0x54)
type_name = "mc1066"; type_name = "mc1066";
} /* LM84 Mfr ID in a different place, and it has more unused bits */
else if (conv_rate == 0x00
&& (config & 0x7F) == 0x00
&& (status & 0xAB) == 0x00)
type_name = "lm84";
else
type_name = "max1617";
pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n",
type_name, i2c_adapter_id(adapter), client->addr); type_name, i2c_adapter_id(adapter), client->addr);
strlcpy(info->type, type_name, I2C_NAME_SIZE); strlcpy(info->type, type_name, I2C_NAME_SIZE);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* adm1025.c * adm1025.c
* *
* Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com> * Copyright (C) 2000 Chen-Yuan Wu <gwu@esoft.com>
* Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2003-2009 Jean Delvare <khali@linux-fr.org>
* *
* The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6
* voltages (including its own power source) and up to two temperatures * voltages (including its own power source) and up to two temperatures
...@@ -413,67 +413,34 @@ static int adm1025_detect(struct i2c_client *client, int kind, ...@@ -413,67 +413,34 @@ static int adm1025_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
const char *name = ""; const char *name;
u8 config; u8 man_id, chip_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* /* Check for unused bits */
* Now we do the remaining detection. A negative kind means that if ((i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG) & 0x80)
* the driver was loaded with no force parameter (default), so we || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0xC0)
* must both detect and identify the chip. A zero kind means that || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0xBC)) {
* the driver was loaded with the force parameter, the detection dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x\n",
* step shall be skipped. A positive kind means that the driver client->addr);
* was loaded with the force parameter and a given kind of chip is return -ENODEV;
* requested, so both the detection and the identification steps
* are skipped.
*/
config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG);
if (kind < 0) { /* detection */
if ((config & 0x80) != 0x00
|| (i2c_smbus_read_byte_data(client,
ADM1025_REG_STATUS1) & 0xC0) != 0x00
|| (i2c_smbus_read_byte_data(client,
ADM1025_REG_STATUS2) & 0xBC) != 0x00) {
dev_dbg(&adapter->dev,
"ADM1025 detection failed at 0x%02x.\n",
client->addr);
return -ENODEV;
}
} }
if (kind <= 0) { /* identification */ /* Identification */
u8 man_id, chip_id; chip_id = i2c_smbus_read_byte_data(client, ADM1025_REG_CHIP_ID);
if ((chip_id & 0xF0) != 0x20)
man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID); return -ENODEV;
chip_id = i2c_smbus_read_byte_data(client, ADM1025_REG_CHIP_ID);
if (man_id == 0x41) { /* Analog Devices */
if ((chip_id & 0xF0) == 0x20) { /* ADM1025/ADM1025A */
kind = adm1025;
}
} else
if (man_id == 0xA1) { /* Philips */
if (client->addr != 0x2E
&& (chip_id & 0xF0) == 0x20) { /* NE1619 */
kind = ne1619;
}
}
if (kind <= 0) { /* identification failed */
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
return -ENODEV;
}
}
if (kind == adm1025) { man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID);
if (man_id == 0x41)
name = "adm1025"; name = "adm1025";
} else if (kind == ne1619) { else if (man_id == 0xA1 && client->addr != 0x2E)
name = "ne1619"; name = "ne1619";
} else
return -ENODEV;
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -1672,35 +1672,26 @@ static int adm1026_detect(struct i2c_client *client, int kind, ...@@ -1672,35 +1672,26 @@ static int adm1026_detect(struct i2c_client *client, int kind,
i2c_adapter_id(client->adapter), client->addr, i2c_adapter_id(client->adapter), client->addr,
company, verstep); company, verstep);
/* If auto-detecting, Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x " i2c_adapter_id(adapter), address);
"...\n", i2c_adapter_id(adapter), address); if (company == ADM1026_COMPANY_ANALOG_DEV
if (company == ADM1026_COMPANY_ANALOG_DEV && verstep == ADM1026_VERSTEP_ADM1026) {
&& verstep == ADM1026_VERSTEP_ADM1026) { /* Analog Devices ADM1026 */
kind = adm1026; } else if (company == ADM1026_COMPANY_ANALOG_DEV
} else if (company == ADM1026_COMPANY_ANALOG_DEV && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
&& (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { dev_err(&adapter->dev, "Unrecognized stepping "
dev_err(&adapter->dev, "Unrecognized stepping " "0x%02x. Defaulting to ADM1026.\n", verstep);
"0x%02x. Defaulting to ADM1026.\n", verstep); } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
kind = adm1026; dev_err(&adapter->dev, "Found version/stepping "
} else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { "0x%02x. Assuming generic ADM1026.\n",
dev_err(&adapter->dev, "Found version/stepping " verstep);
"0x%02x. Assuming generic ADM1026.\n", } else {
verstep); dev_dbg(&adapter->dev, "Autodetection failed\n");
kind = any_chip; /* Not an ADM1026... */
} else { return -ENODEV;
dev_dbg(&adapter->dev, "Autodetection failed\n");
/* Not an ADM1026 ... */
if (kind == 0) { /* User used force=x,y */
dev_err(&adapter->dev, "Generic ADM1026 not "
"found at %d,0x%02x. Try "
"force_adm1026.\n",
i2c_adapter_id(adapter), address);
}
return -ENODEV;
}
} }
strlcpy(info->type, "adm1026", I2C_NAME_SIZE); strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -301,59 +301,36 @@ static int adm1029_detect(struct i2c_client *client, int kind, ...@@ -301,59 +301,36 @@ static int adm1029_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
u8 man_id, chip_id, temp_devices_installed, nb_fan_support;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* Now we do the detection and identification. A negative kind
* means that the driver was loaded with no force parameter
* (default), so we must both detect and identify the chip
* (actually there is only one possible kind of chip for now, adm1029).
* A zero kind means that the driver was loaded with the force
* parameter, the detection step shall be skipped. A positive kind
* means that the driver was loaded with the force parameter and a
* given kind of chip is requested, so both the detection and the
* identification steps are skipped. */
/* Default to an adm1029 if forced */
if (kind == 0)
kind = adm1029;
/* ADM1029 doesn't have CHIP ID, check just MAN ID /* ADM1029 doesn't have CHIP ID, check just MAN ID
* For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED, * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED,
* ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values
* documented * documented
*/ */
if (kind <= 0) { /* identification */ man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID);
u8 man_id, chip_id, temp_devices_installed, nb_fan_support; chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID);
temp_devices_installed = i2c_smbus_read_byte_data(client,
man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID);
chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID);
temp_devices_installed = i2c_smbus_read_byte_data(client,
ADM1029_REG_TEMP_DEVICES_INSTALLED); ADM1029_REG_TEMP_DEVICES_INSTALLED);
nb_fan_support = i2c_smbus_read_byte_data(client, nb_fan_support = i2c_smbus_read_byte_data(client,
ADM1029_REG_NB_FAN_SUPPORT); ADM1029_REG_NB_FAN_SUPPORT);
/* 0x41 is Analog Devices */ /* 0x41 is Analog Devices */
if (man_id == 0x41 && (temp_devices_installed & 0xf9) == 0x01 if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01
&& nb_fan_support == 0x03) { || nb_fan_support != 0x03)
if ((chip_id & 0xF0) == 0x00) { return -ENODEV;
kind = adm1029;
} else {
/* There are no "official" CHIP ID, so actually
* we use Major/Minor revision for that */
printk(KERN_INFO
"adm1029: Unknown major revision %x, "
"please let us know\n", chip_id);
}
}
if (kind <= 0) { /* identification failed */ if ((chip_id & 0xF0) != 0x00) {
pr_debug("adm1029: Unsupported chip (man_id=0x%02X, " /* There are no "official" CHIP ID, so actually
"chip_id=0x%02X)\n", man_id, chip_id); * we use Major/Minor revision for that */
return -ENODEV; pr_info("adm1029: Unknown major revision %x, "
} "please let us know\n", chip_id);
return -ENODEV;
} }
strlcpy(info->type, "adm1029", I2C_NAME_SIZE); strlcpy(info->type, "adm1029", I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -817,31 +817,19 @@ static int adm1031_detect(struct i2c_client *client, int kind, ...@@ -817,31 +817,19 @@ static int adm1031_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
const char *name = ""; const char *name;
int id, co;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind < 0) { id = i2c_smbus_read_byte_data(client, 0x3d);
int id, co; co = i2c_smbus_read_byte_data(client, 0x3e);
id = i2c_smbus_read_byte_data(client, 0x3d);
co = i2c_smbus_read_byte_data(client, 0x3e);
if (!((id == 0x31 || id == 0x30) && co == 0x41)) if (!((id == 0x31 || id == 0x30) && co == 0x41))
return -ENODEV; return -ENODEV;
kind = (id == 0x30) ? adm1030 : adm1031; name = (id == 0x30) ? "adm1030" : "adm1031";
}
if (kind <= 0)
kind = adm1031;
/* Given the detected chip type, set the chip name and the
* auto fan control helper table. */
if (kind == adm1030) {
name = "adm1030";
} else if (kind == adm1031) {
name = "adm1031";
}
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -556,51 +556,34 @@ static int adm9240_detect(struct i2c_client *new_client, int kind, ...@@ -556,51 +556,34 @@ static int adm9240_detect(struct i2c_client *new_client, int kind,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind == 0) { /* verify chip: reg address should match i2c address */
kind = adm9240; if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
} != address) {
dev_err(&adapter->dev, "detect fail: address match, 0x%02x\n",
if (kind < 0) { address);
return -ENODEV;
/* verify chip: reg address should match i2c address */
if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR)
!= address) {
dev_err(&adapter->dev, "detect fail: address match, "
"0x%02x\n", address);
return -ENODEV;
}
/* check known chip manufacturer */
man_id = i2c_smbus_read_byte_data(new_client,
ADM9240_REG_MAN_ID);
if (man_id == 0x23) {
kind = adm9240;
} else if (man_id == 0xda) {
kind = ds1780;
} else if (man_id == 0x01) {
kind = lm81;
} else {
dev_err(&adapter->dev, "detect fail: unknown manuf, "
"0x%02x\n", man_id);
return -ENODEV;
}
/* successful detect, print chip info */
die_rev = i2c_smbus_read_byte_data(new_client,
ADM9240_REG_DIE_REV);
dev_info(&adapter->dev, "found %s revision %u\n",
man_id == 0x23 ? "ADM9240" :
man_id == 0xda ? "DS1780" : "LM81", die_rev);
} }
/* either forced or detected chip kind */ /* check known chip manufacturer */
if (kind == adm9240) { man_id = i2c_smbus_read_byte_data(new_client, ADM9240_REG_MAN_ID);
if (man_id == 0x23) {
name = "adm9240"; name = "adm9240";
} else if (kind == ds1780) { } else if (man_id == 0xda) {
name = "ds1780"; name = "ds1780";
} else if (kind == lm81) { } else if (man_id == 0x01) {
name = "lm81"; name = "lm81";
} else {
dev_err(&adapter->dev, "detect fail: unknown manuf, 0x%02x\n",
man_id);
return -ENODEV;
} }
/* successful detect, print chip info */
die_rev = i2c_smbus_read_byte_data(new_client, ADM9240_REG_DIE_REV);
dev_info(&adapter->dev, "found %s revision %u\n",
man_id == 0x23 ? "ADM9240" :
man_id == 0xda ? "DS1780" : "LM81", die_rev);
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -191,6 +191,7 @@ static int ads7828_detect(struct i2c_client *client, int kind, ...@@ -191,6 +191,7 @@ static int ads7828_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int ch;
/* Check we have a valid client */ /* Check we have a valid client */
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA))
...@@ -202,20 +203,17 @@ static int ads7828_detect(struct i2c_client *client, int kind, ...@@ -202,20 +203,17 @@ static int ads7828_detect(struct i2c_client *client, int kind,
- Read from the 8 channel addresses - Read from the 8 channel addresses
- Check the top 4 bits of each result are not set (12 data bits) - Check the top 4 bits of each result are not set (12 data bits)
*/ */
if (kind < 0) { for (ch = 0; ch < ADS7828_NCH; ch++) {
int ch; u16 in_data;
for (ch = 0; ch < ADS7828_NCH; ch++) { u8 cmd = channel_cmd_byte(ch);
u16 in_data; in_data = ads7828_read_value(client, cmd);
u8 cmd = channel_cmd_byte(ch); if (in_data & 0xF000) {
in_data = ads7828_read_value(client, cmd); pr_debug("%s : Doesn't look like an ads7828 device\n",
if (in_data & 0xF000) { __func__);
printk(KERN_DEBUG return -ENODEV;
"%s : Doesn't look like an ads7828 device\n",
__func__);
return -ENODEV;
}
} }
} }
strlcpy(info->type, "ads7828", I2C_NAME_SIZE); strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -1906,27 +1906,22 @@ static int adt7462_detect(struct i2c_client *client, int kind, ...@@ -1906,27 +1906,22 @@ static int adt7462_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int vendor, device, revision;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind <= 0) { vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR);
int vendor, device, revision; if (vendor != ADT7462_VENDOR)
return -ENODEV;
vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR);
if (vendor != ADT7462_VENDOR)
return -ENODEV;
device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE); device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE);
if (device != ADT7462_DEVICE) if (device != ADT7462_DEVICE)
return -ENODEV; return -ENODEV;
revision = i2c_smbus_read_byte_data(client, revision = i2c_smbus_read_byte_data(client, ADT7462_REG_REVISION);
ADT7462_REG_REVISION); if (revision != ADT7462_REVISION)
if (revision != ADT7462_REVISION) return -ENODEV;
return -ENODEV;
} else
dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(info->type, "adt7462", I2C_NAME_SIZE); strlcpy(info->type, "adt7462", I2C_NAME_SIZE);
......
...@@ -1229,27 +1229,22 @@ static int adt7470_detect(struct i2c_client *client, int kind, ...@@ -1229,27 +1229,22 @@ static int adt7470_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int vendor, device, revision;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind <= 0) { vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR);
int vendor, device, revision; if (vendor != ADT7470_VENDOR)
return -ENODEV;
vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR);
if (vendor != ADT7470_VENDOR)
return -ENODEV;
device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE); device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE);
if (device != ADT7470_DEVICE) if (device != ADT7470_DEVICE)
return -ENODEV; return -ENODEV;
revision = i2c_smbus_read_byte_data(client, revision = i2c_smbus_read_byte_data(client, ADT7470_REG_REVISION);
ADT7470_REG_REVISION); if (revision != ADT7470_REVISION)
if (revision != ADT7470_REVISION) return -ENODEV;
return -ENODEV;
} else
dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(info->type, "adt7470", I2C_NAME_SIZE); strlcpy(info->type, "adt7470", I2C_NAME_SIZE);
......
...@@ -174,7 +174,6 @@ static const struct i2c_device_id adt7473_id[] = { ...@@ -174,7 +174,6 @@ static const struct i2c_device_id adt7473_id[] = {
{ "adt7473", adt7473 }, { "adt7473", adt7473 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, adt7473_id);
static struct i2c_driver adt7473_driver = { static struct i2c_driver adt7473_driver = {
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON,
...@@ -1090,27 +1089,22 @@ static int adt7473_detect(struct i2c_client *client, int kind, ...@@ -1090,27 +1089,22 @@ static int adt7473_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int vendor, device, revision;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind <= 0) { vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
int vendor, device, revision; if (vendor != ADT7473_VENDOR)
return -ENODEV;
vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
if (vendor != ADT7473_VENDOR)
return -ENODEV;
device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE); device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
if (device != ADT7473_DEVICE) if (device != ADT7473_DEVICE)
return -ENODEV; return -ENODEV;
revision = i2c_smbus_read_byte_data(client, revision = i2c_smbus_read_byte_data(client, ADT7473_REG_REVISION);
ADT7473_REG_REVISION); if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69) return -ENODEV;
return -ENODEV;
} else
dev_dbg(&adapter->dev, "detection forced\n");
strlcpy(info->type, "adt7473", I2C_NAME_SIZE); strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
...@@ -1171,6 +1165,8 @@ static int adt7473_remove(struct i2c_client *client) ...@@ -1171,6 +1165,8 @@ static int adt7473_remove(struct i2c_client *client)
static int __init adt7473_init(void) static int __init adt7473_init(void)
{ {
pr_notice("The adt7473 driver is deprecated, please use the adt7475 "
"driver instead\n");
return i2c_add_driver(&adt7473_driver); return i2c_add_driver(&adt7473_driver);
} }
......
此差异已折叠。
...@@ -701,6 +701,7 @@ static int asb100_detect(struct i2c_client *client, int kind, ...@@ -701,6 +701,7 @@ static int asb100_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int val1, val2;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
pr_debug("asb100.o: detect failed, " pr_debug("asb100.o: detect failed, "
...@@ -708,50 +709,30 @@ static int asb100_detect(struct i2c_client *client, int kind, ...@@ -708,50 +709,30 @@ static int asb100_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
} }
/* The chip may be stuck in some other bank than bank 0. This may val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK);
make reading other information impossible. Specify a force=... or val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
force_*=... parameter, and the chip will be reset to the right
bank. */
if (kind < 0) {
int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK);
int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
/* If we're in bank 0 */
if ((!(val1 & 0x07)) &&
/* Check for ASB100 ID (low byte) */
(((!(val1 & 0x80)) && (val2 != 0x94)) ||
/* Check for ASB100 ID (high byte ) */
((val1 & 0x80) && (val2 != 0x06)))) {
pr_debug("asb100.o: detect failed, "
"bad chip id 0x%02x!\n", val2);
return -ENODEV;
}
} /* kind < 0 */ /* If we're in bank 0 */
if ((!(val1 & 0x07)) &&
/* Check for ASB100 ID (low byte) */
(((!(val1 & 0x80)) && (val2 != 0x94)) ||
/* Check for ASB100 ID (high byte ) */
((val1 & 0x80) && (val2 != 0x06)))) {
pr_debug("asb100: detect failed, bad chip id 0x%02x!\n", val2);
return -ENODEV;
}
/* We have either had a force parameter, or we have already detected /* Put it now into bank 0 and Vendor ID High Byte */
Winbond. Put it now into bank 0 and Vendor ID High Byte */
i2c_smbus_write_byte_data(client, ASB100_REG_BANK, i2c_smbus_write_byte_data(client, ASB100_REG_BANK,
(i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78) (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78)
| 0x80); | 0x80);
/* Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID);
int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID); val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
if (val1 != 0x31 || val2 != 0x06)
if ((val1 == 0x31) && (val2 == 0x06)) return -ENODEV;
kind = asb100;
else {
if (kind == 0)
dev_warn(&adapter->dev, "ignoring "
"'force' parameter for unknown chip "
"at adapter %d, address 0x%02x.\n",
i2c_adapter_id(adapter), client->addr);
return -ENODEV;
}
}
strlcpy(info->type, "asb100", I2C_NAME_SIZE); strlcpy(info->type, "asb100", I2C_NAME_SIZE);
......
...@@ -2220,33 +2220,23 @@ static int dme1737_i2c_detect(struct i2c_client *client, int kind, ...@@ -2220,33 +2220,23 @@ static int dme1737_i2c_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
} }
/* A negative kind means that the driver was loaded with no force company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY);
* parameter (default), so we must identify the chip. */ verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP);
if (kind < 0) {
company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY);
verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP);
if (company == DME1737_COMPANY_SMSC &&
(verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
kind = dme1737;
} else if (company == DME1737_COMPANY_SMSC &&
verstep == SCH5027_VERSTEP) {
kind = sch5027;
} else {
return -ENODEV;
}
}
if (kind == sch5027) { if (company == DME1737_COMPANY_SMSC &&
verstep == SCH5027_VERSTEP) {
name = "sch5027"; name = "sch5027";
} else {
kind = dme1737; } else if (company == DME1737_COMPANY_SMSC &&
(verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
name = "dme1737"; name = "dme1737";
} else {
return -ENODEV;
} }
dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n", dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n",
kind == sch5027 ? "SCH5027" : "DME1737", client->addr, verstep == SCH5027_VERSTEP ? "SCH5027" : "DME1737",
verstep); client->addr, verstep);
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -237,20 +237,16 @@ static int ds1621_detect(struct i2c_client *client, int kind, ...@@ -237,20 +237,16 @@ static int ds1621_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
/* Now, we do the remaining detection. It is lousy. */ /* Now, we do the remaining detection. It is lousy. */
if (kind < 0) { /* The NVB bit should be low if no EEPROM write has been requested
/* The NVB bit should be low if no EEPROM write has been during the latest 10ms, which is highly improbable in our case. */
requested during the latest 10ms, which is highly conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
improbable in our case. */ if (conf < 0 || conf & DS1621_REG_CONFIG_NVB)
conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); return -ENODEV;
if (conf < 0 || conf & DS1621_REG_CONFIG_NVB) /* The 7 lowest bits of a temperature should always be 0. */
for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) {
temp = i2c_smbus_read_word_data(client, DS1621_REG_TEMP[i]);
if (temp < 0 || (temp & 0x7f00))
return -ENODEV; return -ENODEV;
/* The 7 lowest bits of a temperature should always be 0. */
for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) {
temp = i2c_smbus_read_word_data(client,
DS1621_REG_TEMP[i]);
if (temp < 0 || (temp & 0x7f00))
return -ENODEV;
}
} }
strlcpy(info->type, "ds1621", I2C_NAME_SIZE); strlcpy(info->type, "ds1621", I2C_NAME_SIZE);
......
此差异已折叠。
...@@ -681,30 +681,20 @@ static int f75375_detect(struct i2c_client *client, int kind, ...@@ -681,30 +681,20 @@ static int f75375_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
u8 version = 0; u16 vendid, chipid;
const char *name = ""; u8 version;
const char *name;
if (kind < 0) {
u16 vendid = f75375_read16(client, F75375_REG_VENDOR);
u16 chipid = f75375_read16(client, F75375_CHIP_ID);
version = f75375_read8(client, F75375_REG_VERSION);
if (chipid == 0x0306 && vendid == 0x1934) {
kind = f75375;
} else if (chipid == 0x0204 && vendid == 0x1934) {
kind = f75373;
} else {
dev_err(&adapter->dev,
"failed,%02X,%02X,%02X\n",
chipid, version, vendid);
return -ENODEV;
}
}
if (kind == f75375) { vendid = f75375_read16(client, F75375_REG_VENDOR);
chipid = f75375_read16(client, F75375_CHIP_ID);
if (chipid == 0x0306 && vendid == 0x1934)
name = "f75375"; name = "f75375";
} else if (kind == f75373) { else if (chipid == 0x0204 && vendid == 0x1934)
name = "f75373"; name = "f75373";
} else
return -ENODEV;
version = f75375_read8(client, F75375_REG_VERSION);
dev_info(&adapter->dev, "found %s version: %02X\n", name, version); dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
......
...@@ -1000,43 +1000,38 @@ static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy) ...@@ -1000,43 +1000,38 @@ static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy)
} }
} }
static int fschmd_detect(struct i2c_client *client, int kind, static int fschmd_detect(struct i2c_client *client, int _kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
enum chips kind;
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
char id[4];
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* Detect & Identify the chip */ /* Detect & Identify the chip */
if (kind <= 0) { id[0] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_0);
char id[4]; id[1] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_1);
id[2] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_2);
id[0] = i2c_smbus_read_byte_data(client, id[3] = '\0';
FSCHMD_REG_IDENT_0);
id[1] = i2c_smbus_read_byte_data(client, if (!strcmp(id, "PEG"))
FSCHMD_REG_IDENT_1); kind = fscpos;
id[2] = i2c_smbus_read_byte_data(client, else if (!strcmp(id, "HER"))
FSCHMD_REG_IDENT_2); kind = fscher;
id[3] = '\0'; else if (!strcmp(id, "SCY"))
kind = fscscy;
if (!strcmp(id, "PEG")) else if (!strcmp(id, "HRC"))
kind = fscpos; kind = fschrc;
else if (!strcmp(id, "HER")) else if (!strcmp(id, "HMD"))
kind = fscher; kind = fschmd;
else if (!strcmp(id, "SCY")) else if (!strcmp(id, "HDS"))
kind = fscscy; kind = fschds;
else if (!strcmp(id, "HRC")) else if (!strcmp(id, "SYL"))
kind = fschrc; kind = fscsyl;
else if (!strcmp(id, "HMD")) else
kind = fschmd; return -ENODEV;
else if (!strcmp(id, "HDS"))
kind = fschds;
else if (!strcmp(id, "SYL"))
kind = fscsyl;
else
return -ENODEV;
}
strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE); strlcpy(info->type, fschmd_id[kind - 1].name, I2C_NAME_SIZE);
......
...@@ -488,36 +488,21 @@ static int gl518_detect(struct i2c_client *client, int kind, ...@@ -488,36 +488,21 @@ static int gl518_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int i; int rev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV; return -ENODEV;
/* Now, we do the remaining detection. */ /* Now, we do the remaining detection. */
if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80)
if (kind < 0) { || (gl518_read_value(client, GL518_REG_CONF) & 0x80))
if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80) return -ENODEV;
|| (gl518_read_value(client, GL518_REG_CONF) & 0x80))
return -ENODEV;
}
/* Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { rev = gl518_read_value(client, GL518_REG_REVISION);
i = gl518_read_value(client, GL518_REG_REVISION); if (rev != 0x00 && rev != 0x80)
if (i == 0x00) { return -ENODEV;
kind = gl518sm_r00;
} else if (i == 0x80) {
kind = gl518sm_r80;
} else {
if (kind <= 0)
dev_info(&adapter->dev,
"Ignoring 'force' parameter for unknown "
"chip at adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), client->addr);
return -ENODEV;
}
}
strlcpy(info->type, "gl518sm", I2C_NAME_SIZE); strlcpy(info->type, "gl518sm", I2C_NAME_SIZE);
......
...@@ -691,13 +691,11 @@ static int gl520_detect(struct i2c_client *client, int kind, ...@@ -691,13 +691,11 @@ static int gl520_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
/* Determine the chip type. */ /* Determine the chip type. */
if (kind < 0) { if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) ||
if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) || ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) ||
((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) {
((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { dev_dbg(&client->dev, "Unknown chip type, skipping\n");
dev_dbg(&client->dev, "Unknown chip type, skipping\n"); return -ENODEV;
return -ENODEV;
}
} }
strlcpy(info->type, "gl520sm", I2C_NAME_SIZE); strlcpy(info->type, "gl520sm", I2C_NAME_SIZE);
......
...@@ -124,6 +124,8 @@ superio_exit(void) ...@@ -124,6 +124,8 @@ superio_exit(void)
#define IT87_BASE_REG 0x60 #define IT87_BASE_REG 0x60
/* Logical device 7 registers (IT8712F and later) */ /* Logical device 7 registers (IT8712F and later) */
#define IT87_SIO_GPIO3_REG 0x27
#define IT87_SIO_GPIO5_REG 0x29
#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ #define IT87_SIO_PINX2_REG 0x2c /* Pin selection */
#define IT87_SIO_VID_REG 0xfc /* VID value */ #define IT87_SIO_VID_REG 0xfc /* VID value */
...@@ -244,7 +246,9 @@ struct it87_sio_data { ...@@ -244,7 +246,9 @@ struct it87_sio_data {
/* Values read from Super-I/O config space */ /* Values read from Super-I/O config space */
u8 revision; u8 revision;
u8 vid_value; u8 vid_value;
/* Values set based on DMI strings */ /* Features skipped based on config or DMI */
u8 skip_vid;
u8 skip_fan;
u8 skip_pwm; u8 skip_pwm;
}; };
...@@ -1028,11 +1032,35 @@ static int __init it87_find(unsigned short *address, ...@@ -1028,11 +1032,35 @@ static int __init it87_find(unsigned short *address,
chip_type, *address, sio_data->revision); chip_type, *address, sio_data->revision);
/* Read GPIO config and VID value from LDN 7 (GPIO) */ /* Read GPIO config and VID value from LDN 7 (GPIO) */
if (sio_data->type != it87) { if (sio_data->type == it87) {
/* The IT8705F doesn't have VID pins at all */
sio_data->skip_vid = 1;
} else {
int reg; int reg;
superio_select(GPIO); superio_select(GPIO);
if (sio_data->type == it8718 || sio_data->type == it8720) /* We need at least 4 VID pins */
reg = superio_inb(IT87_SIO_GPIO3_REG);
if (reg & 0x0f) {
pr_info("it87: VID is disabled (pins used for GPIO)\n");
sio_data->skip_vid = 1;
}
/* Check if fan3 is there or not */
if (reg & (1 << 6))
sio_data->skip_pwm |= (1 << 2);
if (reg & (1 << 7))
sio_data->skip_fan |= (1 << 2);
/* Check if fan2 is there or not */
reg = superio_inb(IT87_SIO_GPIO5_REG);
if (reg & (1 << 1))
sio_data->skip_pwm |= (1 << 1);
if (reg & (1 << 2))
sio_data->skip_fan |= (1 << 1);
if ((sio_data->type == it8718 || sio_data->type == it8720)
&& !(sio_data->skip_vid))
sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
reg = superio_inb(IT87_SIO_PINX2_REG); reg = superio_inb(IT87_SIO_PINX2_REG);
...@@ -1236,8 +1264,7 @@ static int __devinit it87_probe(struct platform_device *pdev) ...@@ -1236,8 +1264,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
} }
} }
if (data->type == it8712 || data->type == it8716 if (!sio_data->skip_vid) {
|| data->type == it8718 || data->type == it8720) {
data->vrm = vid_which_vrm(); data->vrm = vid_which_vrm();
/* VID reading from Super-I/O config space if available */ /* VID reading from Super-I/O config space if available */
data->vid = sio_data->vid_value; data->vid = sio_data->vid_value;
...@@ -1355,8 +1382,10 @@ static int __devinit it87_check_pwm(struct device *dev) ...@@ -1355,8 +1382,10 @@ static int __devinit it87_check_pwm(struct device *dev)
/* Called when we have found a new IT87. */ /* Called when we have found a new IT87. */
static void __devinit it87_init_device(struct platform_device *pdev) static void __devinit it87_init_device(struct platform_device *pdev)
{ {
struct it87_sio_data *sio_data = pdev->dev.platform_data;
struct it87_data *data = platform_get_drvdata(pdev); struct it87_data *data = platform_get_drvdata(pdev);
int tmp, i; int tmp, i;
u8 mask;
/* initialize to sane defaults: /* initialize to sane defaults:
* - if the chip is in manual pwm mode, this will be overwritten with * - if the chip is in manual pwm mode, this will be overwritten with
...@@ -1402,10 +1431,11 @@ static void __devinit it87_init_device(struct platform_device *pdev) ...@@ -1402,10 +1431,11 @@ static void __devinit it87_init_device(struct platform_device *pdev)
} }
/* Check if tachometers are reset manually or by some reason */ /* Check if tachometers are reset manually or by some reason */
mask = 0x70 & ~(sio_data->skip_fan << 4);
data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL);
if ((data->fan_main_ctrl & 0x70) == 0) { if ((data->fan_main_ctrl & mask) == 0) {
/* Enable all fan tachometers */ /* Enable all fan tachometers */
data->fan_main_ctrl |= 0x70; data->fan_main_ctrl |= mask;
it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl); it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
} }
data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
...@@ -1428,6 +1458,9 @@ static void __devinit it87_init_device(struct platform_device *pdev) ...@@ -1428,6 +1458,9 @@ static void __devinit it87_init_device(struct platform_device *pdev)
} }
} }
/* Fan input pins may be used for alternative functions */
data->has_fan &= ~sio_data->skip_fan;
/* Set current fan mode registers and the default settings for the /* Set current fan mode registers and the default settings for the
* other mode registers */ * other mode registers */
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
......
...@@ -427,40 +427,34 @@ static int lm63_detect(struct i2c_client *new_client, int kind, ...@@ -427,40 +427,34 @@ static int lm63_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
u8 man_id, chip_id, reg_config1, reg_config2;
u8 reg_alert_status, reg_alert_mask;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind < 0) { /* must identify */ man_id = i2c_smbus_read_byte_data(new_client, LM63_REG_MAN_ID);
u8 man_id, chip_id, reg_config1, reg_config2; chip_id = i2c_smbus_read_byte_data(new_client, LM63_REG_CHIP_ID);
u8 reg_alert_status, reg_alert_mask;
reg_config1 = i2c_smbus_read_byte_data(new_client,
man_id = i2c_smbus_read_byte_data(new_client, LM63_REG_CONFIG1);
LM63_REG_MAN_ID); reg_config2 = i2c_smbus_read_byte_data(new_client,
chip_id = i2c_smbus_read_byte_data(new_client, LM63_REG_CONFIG2);
LM63_REG_CHIP_ID); reg_alert_status = i2c_smbus_read_byte_data(new_client,
reg_config1 = i2c_smbus_read_byte_data(new_client, LM63_REG_ALERT_STATUS);
LM63_REG_CONFIG1); reg_alert_mask = i2c_smbus_read_byte_data(new_client,
reg_config2 = i2c_smbus_read_byte_data(new_client, LM63_REG_ALERT_MASK);
LM63_REG_CONFIG2);
reg_alert_status = i2c_smbus_read_byte_data(new_client, if (man_id != 0x01 /* National Semiconductor */
LM63_REG_ALERT_STATUS); || chip_id != 0x41 /* LM63 */
reg_alert_mask = i2c_smbus_read_byte_data(new_client, || (reg_config1 & 0x18) != 0x00
LM63_REG_ALERT_MASK); || (reg_config2 & 0xF8) != 0x00
|| (reg_alert_status & 0x20) != 0x00
if (man_id == 0x01 /* National Semiconductor */ || (reg_alert_mask & 0xA4) != 0xA4) {
&& chip_id == 0x41 /* LM63 */ dev_dbg(&adapter->dev,
&& (reg_config1 & 0x18) == 0x00 "Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n",
&& (reg_config2 & 0xF8) == 0x00 man_id, chip_id);
&& (reg_alert_status & 0x20) == 0x00 return -ENODEV;
&& (reg_alert_mask & 0xA4) == 0xA4) {
kind = lm63;
} else { /* failed */
dev_dbg(&adapter->dev, "Unsupported chip "
"(man_id=0x%02X, chip_id=0x%02X).\n",
man_id, chip_id);
return -ENODEV;
}
} }
strlcpy(info->type, "lm63", I2C_NAME_SIZE); strlcpy(info->type, "lm63", I2C_NAME_SIZE);
......
/*
* LM73 Sensor driver
* Based on LM75
*
* Copyright (C) 2007, CenoSYS (www.cenosys.com).
* Copyright (C) 2009, Bollore telecom (www.bolloretelecom.eu).
*
* Guillaume Ligneul <guillaume.ligneul@gmail.com>
* Adrien Demarez <adrien.demarez@bolloretelecom.eu>
* Jeremy Laine <jeremy.laine@bolloretelecom.eu>
*
* This software program is licensed subject to the GNU General Public License
* (GPL).Version 2,June 1991, available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/hwmon.h>
#include <linux/hwmon-sysfs.h>
#include <linux/err.h>
/* Addresses scanned */
static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c,
0x4d, 0x4e, I2C_CLIENT_END };
/* Insmod parameters */
I2C_CLIENT_INSMOD_1(lm73);
/* LM73 registers */
#define LM73_REG_INPUT 0x00
#define LM73_REG_CONF 0x01
#define LM73_REG_MAX 0x02
#define LM73_REG_MIN 0x03
#define LM73_REG_CTRL 0x04
#define LM73_REG_ID 0x07
#define LM73_ID 0x9001 /* or 0x190 after a swab16() */
#define DRVNAME "lm73"
#define LM73_TEMP_MIN (-40)
#define LM73_TEMP_MAX 150
/*-----------------------------------------------------------------------*/
static ssize_t set_temp(struct device *dev, struct device_attribute *da,
const char *buf, size_t count)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
long temp;
short value;
int status = strict_strtol(buf, 10, &temp);
if (status < 0)
return status;
/* Write value */
value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4),
(LM73_TEMP_MAX*4)) << 5;
i2c_smbus_write_word_data(client, attr->index, swab16(value));
return count;
}
static ssize_t show_temp(struct device *dev, struct device_attribute *da,
char *buf)
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev);
/* use integer division instead of equivalent right shift to
guarantee arithmetic shift and preserve the sign */
int temp = ((s16) (swab16(i2c_smbus_read_word_data(client,
attr->index)))*250) / 32;
return sprintf(buf, "%d\n", temp);
}
/*-----------------------------------------------------------------------*/
/* sysfs attributes for hwmon */
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
show_temp, set_temp, LM73_REG_MAX);
static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
show_temp, set_temp, LM73_REG_MIN);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
show_temp, NULL, LM73_REG_INPUT);
static struct attribute *lm73_attributes[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_min.dev_attr.attr,
NULL
};
static const struct attribute_group lm73_group = {
.attrs = lm73_attributes,
};
/*-----------------------------------------------------------------------*/
/* device probe and removal */
static int
lm73_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
struct device *hwmon_dev;
int status;
/* Register sysfs hooks */
status = sysfs_create_group(&client->dev.kobj, &lm73_group);
if (status)
return status;
hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(hwmon_dev)) {
status = PTR_ERR(hwmon_dev);
goto exit_remove;
}
i2c_set_clientdata(client, hwmon_dev);
dev_info(&client->dev, "%s: sensor '%s'\n",
dev_name(hwmon_dev), client->name);
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &lm73_group);
return status;
}
static int lm73_remove(struct i2c_client *client)
{
struct device *hwmon_dev = i2c_get_clientdata(client);
hwmon_device_unregister(hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm73_group);
i2c_set_clientdata(client, NULL);
return 0;
}
static const struct i2c_device_id lm73_ids[] = {
{ "lm73", lm73 },
{ /* LIST END */ }
};
MODULE_DEVICE_TABLE(i2c, lm73_ids);
/* Return 0 if detection is successful, -ENODEV otherwise */
static int lm73_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info)
{
struct i2c_adapter *adapter = new_client->adapter;
u16 id;
u8 ctrl;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
/* Check device ID */
id = i2c_smbus_read_word_data(new_client, LM73_REG_ID);
ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL);
if ((id != LM73_ID) || (ctrl & 0x10))
return -ENODEV;
strlcpy(info->type, "lm73", I2C_NAME_SIZE);
return 0;
}
static struct i2c_driver lm73_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "lm73",
},
.probe = lm73_probe,
.remove = lm73_remove,
.id_table = lm73_ids,
.detect = lm73_detect,
.address_data = &addr_data,
};
/* module glue */
static int __init sensors_lm73_init(void)
{
return i2c_add_driver(&lm73_driver);
}
static void __exit sensors_lm73_exit(void)
{
i2c_del_driver(&lm73_driver);
}
MODULE_AUTHOR("Guillaume Ligneul <guillaume.ligneul@gmail.com>");
MODULE_DESCRIPTION("LM73 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm73_init);
module_exit(sensors_lm73_exit);
...@@ -239,6 +239,7 @@ static int lm75_detect(struct i2c_client *new_client, int kind, ...@@ -239,6 +239,7 @@ static int lm75_detect(struct i2c_client *new_client, int kind,
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int i; int i;
int cur, conf, hyst, os;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
...@@ -251,40 +252,35 @@ static int lm75_detect(struct i2c_client *new_client, int kind, ...@@ -251,40 +252,35 @@ static int lm75_detect(struct i2c_client *new_client, int kind,
The cycling+unused addresses combination is not tested, The cycling+unused addresses combination is not tested,
since it would significantly slow the detection down and would since it would significantly slow the detection down and would
hardly add any value. */ hardly add any value. */
if (kind < 0) {
int cur, conf, hyst, os;
/* Unused addresses */
cur = i2c_smbus_read_word_data(new_client, 0);
conf = i2c_smbus_read_byte_data(new_client, 1);
hyst = i2c_smbus_read_word_data(new_client, 2);
if (i2c_smbus_read_word_data(new_client, 4) != hyst
|| i2c_smbus_read_word_data(new_client, 5) != hyst
|| i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst)
return -ENODEV;
os = i2c_smbus_read_word_data(new_client, 3);
if (i2c_smbus_read_word_data(new_client, 4) != os
|| i2c_smbus_read_word_data(new_client, 5) != os
|| i2c_smbus_read_word_data(new_client, 6) != os
|| i2c_smbus_read_word_data(new_client, 7) != os)
return -ENODEV;
/* Unused bits */ /* Unused addresses */
if (conf & 0xe0) cur = i2c_smbus_read_word_data(new_client, 0);
return -ENODEV; conf = i2c_smbus_read_byte_data(new_client, 1);
hyst = i2c_smbus_read_word_data(new_client, 2);
if (i2c_smbus_read_word_data(new_client, 4) != hyst
|| i2c_smbus_read_word_data(new_client, 5) != hyst
|| i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst)
return -ENODEV;
os = i2c_smbus_read_word_data(new_client, 3);
if (i2c_smbus_read_word_data(new_client, 4) != os
|| i2c_smbus_read_word_data(new_client, 5) != os
|| i2c_smbus_read_word_data(new_client, 6) != os
|| i2c_smbus_read_word_data(new_client, 7) != os)
return -ENODEV;
/* Addresses cycling */ /* Unused bits */
for (i = 8; i < 0xff; i += 8) if (conf & 0xe0)
if (i2c_smbus_read_byte_data(new_client, i + 1) != conf return -ENODEV;
|| i2c_smbus_read_word_data(new_client, i + 2) != hyst
|| i2c_smbus_read_word_data(new_client, i + 3) != os) /* Addresses cycling */
return -ENODEV; for (i = 8; i < 0xff; i += 8) {
if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
|| i2c_smbus_read_word_data(new_client, i + 2) != hyst
|| i2c_smbus_read_word_data(new_client, i + 3) != os)
return -ENODEV;
} }
/* NOTE: we treat "force=..." and "force_lm75=..." the same.
* Only new-style driver binding distinguishes chip types.
*/
strlcpy(info->type, "lm75", I2C_NAME_SIZE); strlcpy(info->type, "lm75", I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -249,6 +249,7 @@ static int lm77_detect(struct i2c_client *new_client, int kind, ...@@ -249,6 +249,7 @@ static int lm77_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int i, cur, conf, hyst, crit, min, max;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_WORD_DATA))
...@@ -265,51 +266,48 @@ static int lm77_detect(struct i2c_client *new_client, int kind, ...@@ -265,51 +266,48 @@ static int lm77_detect(struct i2c_client *new_client, int kind,
4. registers cycling over 8-address boundaries 4. registers cycling over 8-address boundaries
Word-sized registers are high-byte first. */ Word-sized registers are high-byte first. */
if (kind < 0) {
int i, cur, conf, hyst, crit, min, max;
/* addresses cycling */
cur = i2c_smbus_read_word_data(new_client, 0);
conf = i2c_smbus_read_byte_data(new_client, 1);
hyst = i2c_smbus_read_word_data(new_client, 2);
crit = i2c_smbus_read_word_data(new_client, 3);
min = i2c_smbus_read_word_data(new_client, 4);
max = i2c_smbus_read_word_data(new_client, 5);
for (i = 8; i <= 0xff; i += 8)
if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
|| i2c_smbus_read_word_data(new_client, i + 2) != hyst
|| i2c_smbus_read_word_data(new_client, i + 3) != crit
|| i2c_smbus_read_word_data(new_client, i + 4) != min
|| i2c_smbus_read_word_data(new_client, i + 5) != max)
return -ENODEV;
/* sign bits */
if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0)
|| ((hyst & 0x00f0) != 0xf0 && (hyst & 0x00f0) != 0x0)
|| ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0)
|| ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0)
|| ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0))
return -ENODEV;
/* unused bits */ /* addresses cycling */
if (conf & 0xe0) cur = i2c_smbus_read_word_data(new_client, 0);
conf = i2c_smbus_read_byte_data(new_client, 1);
hyst = i2c_smbus_read_word_data(new_client, 2);
crit = i2c_smbus_read_word_data(new_client, 3);
min = i2c_smbus_read_word_data(new_client, 4);
max = i2c_smbus_read_word_data(new_client, 5);
for (i = 8; i <= 0xff; i += 8) {
if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
|| i2c_smbus_read_word_data(new_client, i + 2) != hyst
|| i2c_smbus_read_word_data(new_client, i + 3) != crit
|| i2c_smbus_read_word_data(new_client, i + 4) != min
|| i2c_smbus_read_word_data(new_client, i + 5) != max)
return -ENODEV; return -ENODEV;
}
/* 0x06 and 0x07 return the last read value */ /* sign bits */
cur = i2c_smbus_read_word_data(new_client, 0); if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0)
if (i2c_smbus_read_word_data(new_client, 6) != cur || ((hyst & 0x00f0) != 0xf0 && (hyst & 0x00f0) != 0x0)
|| i2c_smbus_read_word_data(new_client, 7) != cur) || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0)
return -ENODEV; || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0)
hyst = i2c_smbus_read_word_data(new_client, 2); || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0))
if (i2c_smbus_read_word_data(new_client, 6) != hyst return -ENODEV;
|| i2c_smbus_read_word_data(new_client, 7) != hyst)
return -ENODEV;
min = i2c_smbus_read_word_data(new_client, 4);
if (i2c_smbus_read_word_data(new_client, 6) != min
|| i2c_smbus_read_word_data(new_client, 7) != min)
return -ENODEV;
} /* unused bits */
if (conf & 0xe0)
return -ENODEV;
/* 0x06 and 0x07 return the last read value */
cur = i2c_smbus_read_word_data(new_client, 0);
if (i2c_smbus_read_word_data(new_client, 6) != cur
|| i2c_smbus_read_word_data(new_client, 7) != cur)
return -ENODEV;
hyst = i2c_smbus_read_word_data(new_client, 2);
if (i2c_smbus_read_word_data(new_client, 6) != hyst
|| i2c_smbus_read_word_data(new_client, 7) != hyst)
return -ENODEV;
min = i2c_smbus_read_word_data(new_client, 4);
if (i2c_smbus_read_word_data(new_client, 6) != min
|| i2c_smbus_read_word_data(new_client, 7) != min)
return -ENODEV;
strlcpy(info->type, "lm77", I2C_NAME_SIZE); strlcpy(info->type, "lm77", I2C_NAME_SIZE);
......
...@@ -576,52 +576,34 @@ static int lm78_i2c_detect(struct i2c_client *client, int kind, ...@@ -576,52 +576,34 @@ static int lm78_i2c_detect(struct i2c_client *client, int kind,
if (isa) if (isa)
mutex_lock(&isa->update_lock); mutex_lock(&isa->update_lock);
if (kind < 0) { if ((i2c_smbus_read_byte_data(client, LM78_REG_CONFIG) & 0x80)
if ((i2c_smbus_read_byte_data(client, LM78_REG_CONFIG) & 0x80) || i2c_smbus_read_byte_data(client, LM78_REG_I2C_ADDR) != address)
|| i2c_smbus_read_byte_data(client, LM78_REG_I2C_ADDR) goto err_nodev;
!= address)
goto err_nodev; /* Explicitly prevent the misdetection of Winbond chips */
i = i2c_smbus_read_byte_data(client, 0x4f);
/* Explicitly prevent the misdetection of Winbond chips */ if (i == 0xa3 || i == 0x5c)
i = i2c_smbus_read_byte_data(client, 0x4f); goto err_nodev;
if (i == 0xa3 || i == 0x5c)
goto err_nodev;
}
/* Determine the chip type. */ /* Determine the chip type. */
if (kind <= 0) { i = i2c_smbus_read_byte_data(client, LM78_REG_CHIPID);
i = i2c_smbus_read_byte_data(client, LM78_REG_CHIPID); if (i == 0x00 || i == 0x20 /* LM78 */
if (i == 0x00 || i == 0x20 /* LM78 */ || i == 0x40) /* LM78-J */
|| i == 0x40) /* LM78-J */ client_name = "lm78";
kind = lm78; else if ((i & 0xfe) == 0xc0)
else if ((i & 0xfe) == 0xc0) client_name = "lm79";
kind = lm79; else
else { goto err_nodev;
if (kind == 0)
dev_warn(&adapter->dev, "Ignoring 'force' "
"parameter for unknown chip at "
"adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address);
goto err_nodev;
}
if (lm78_alias_detect(client, i)) { if (lm78_alias_detect(client, i)) {
dev_dbg(&adapter->dev, "Device at 0x%02x appears to " dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
"be the same as ISA device\n", address); "be the same as ISA device\n", address);
goto err_nodev; goto err_nodev;
}
} }
if (isa) if (isa)
mutex_unlock(&isa->update_lock); mutex_unlock(&isa->update_lock);
switch (kind) {
case lm79:
client_name = "lm79";
break;
default:
client_name = "lm78";
}
strlcpy(info->type, client_name, I2C_NAME_SIZE); strlcpy(info->type, client_name, I2C_NAME_SIZE);
return 0; return 0;
......
/* /*
* lm83.c - Part of lm_sensors, Linux kernel modules for hardware * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring * monitoring
* Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2003-2009 Jean Delvare <khali@linux-fr.org>
* *
* Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is
* a sensor chip made by National Semiconductor. It reports up to four * a sensor chip made by National Semiconductor. It reports up to four
...@@ -295,69 +295,40 @@ static int lm83_detect(struct i2c_client *new_client, int kind, ...@@ -295,69 +295,40 @@ static int lm83_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
const char *name = ""; const char *name;
u8 man_id, chip_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* Now we do the detection and identification. A negative kind /* Detection */
* means that the driver was loaded with no force parameter if ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1) & 0xA8) ||
* (default), so we must both detect and identify the chip (i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2) & 0x48) ||
* (actually there is only one possible kind of chip for now, LM83). (i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41)) {
* A zero kind means that the driver was loaded with the force dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n",
* parameter, the detection step shall be skipped. A positive kind new_client->addr);
* means that the driver was loaded with the force parameter and a return -ENODEV;
* given kind of chip is requested, so both the detection and the
* identification steps are skipped. */
/* Default to an LM83 if forced */
if (kind == 0)
kind = lm83;
if (kind < 0) { /* detection */
if (((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1)
& 0xA8) != 0x00) ||
((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2)
& 0x48) != 0x00) ||
((i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG)
& 0x41) != 0x00)) {
dev_dbg(&adapter->dev,
"LM83 detection failed at 0x%02x.\n",
new_client->addr);
return -ENODEV;
}
} }
if (kind <= 0) { /* identification */ /* Identification */
u8 man_id, chip_id; man_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_MAN_ID);
if (man_id != 0x01) /* National Semiconductor */
man_id = i2c_smbus_read_byte_data(new_client, return -ENODEV;
LM83_REG_R_MAN_ID);
chip_id = i2c_smbus_read_byte_data(new_client,
LM83_REG_R_CHIP_ID);
if (man_id == 0x01) { /* National Semiconductor */
if (chip_id == 0x03) {
kind = lm83;
} else
if (chip_id == 0x01) {
kind = lm82;
}
}
if (kind <= 0) { /* identification failed */
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
return -ENODEV;
}
}
if (kind == lm83) { chip_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_CHIP_ID);
switch (chip_id) {
case 0x03:
name = "lm83"; name = "lm83";
} else break;
if (kind == lm82) { case 0x01:
name = "lm82"; name = "lm82";
break;
default:
/* identification failed */
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n",
man_id, chip_id);
return -ENODEV;
} }
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com> Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de> Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com> Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
Copyright (C) 2007, 2008 Jean Delvare <khali@linux-fr.org> Copyright (C) 2007--2009 Jean Delvare <khali@linux-fr.org>
Chip details at <http://www.national.com/ds/LM/LM85.pdf> Chip details at <http://www.national.com/ds/LM/LM85.pdf>
...@@ -1162,107 +1162,80 @@ static int lm85_detect(struct i2c_client *client, int kind, ...@@ -1162,107 +1162,80 @@ static int lm85_detect(struct i2c_client *client, int kind,
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int address = client->addr; int address = client->addr;
const char *type_name; const char *type_name;
int company, verstep;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
/* We need to be able to do byte I/O */ /* We need to be able to do byte I/O */
return -ENODEV; return -ENODEV;
} }
/* If auto-detecting, determine the chip type */ /* Determine the chip type */
if (kind < 0) { company = lm85_read_value(client, LM85_REG_COMPANY);
int company = lm85_read_value(client, LM85_REG_COMPANY); verstep = lm85_read_value(client, LM85_REG_VERSTEP);
int verstep = lm85_read_value(client, LM85_REG_VERSTEP);
dev_dbg(&adapter->dev, "Detecting device at 0x%02x with "
dev_dbg(&adapter->dev, "Detecting device at 0x%02x with " "COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
"COMPANY: 0x%02x and VERSTEP: 0x%02x\n", address, company, verstep);
address, company, verstep);
/* All supported chips have the version in common */
/* All supported chips have the version in common */ if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC &&
if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) {
(verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { dev_dbg(&adapter->dev,
dev_dbg(&adapter->dev, "Autodetection failed: " "Autodetection failed: unsupported version\n");
"unsupported version\n"); return -ENODEV;
return -ENODEV; }
} type_name = "lm85";
kind = any_chip;
/* Now, refine the detection */
/* Now, refine the detection */ if (company == LM85_COMPANY_NATIONAL) {
if (company == LM85_COMPANY_NATIONAL) { switch (verstep) {
switch (verstep) { case LM85_VERSTEP_LM85C:
case LM85_VERSTEP_LM85C: type_name = "lm85c";
kind = lm85c; break;
break; case LM85_VERSTEP_LM85B:
case LM85_VERSTEP_LM85B: type_name = "lm85b";
kind = lm85b; break;
break; case LM85_VERSTEP_LM96000_1:
case LM85_VERSTEP_LM96000_1: case LM85_VERSTEP_LM96000_2:
case LM85_VERSTEP_LM96000_2: /* Check for Winbond WPCD377I */
/* Check for Winbond WPCD377I */ if (lm85_is_fake(client)) {
if (lm85_is_fake(client)) { dev_dbg(&adapter->dev,
dev_dbg(&adapter->dev, "Found Winbond WPCD377I, ignoring\n");
"Found Winbond WPCD377I, " return -ENODEV;
"ignoring\n");
return -ENODEV;
}
break;
}
} else if (company == LM85_COMPANY_ANALOG_DEV) {
switch (verstep) {
case LM85_VERSTEP_ADM1027:
kind = adm1027;
break;
case LM85_VERSTEP_ADT7463:
case LM85_VERSTEP_ADT7463C:
kind = adt7463;
break;
case LM85_VERSTEP_ADT7468_1:
case LM85_VERSTEP_ADT7468_2:
kind = adt7468;
break;
}
} else if (company == LM85_COMPANY_SMSC) {
switch (verstep) {
case LM85_VERSTEP_EMC6D100_A0:
case LM85_VERSTEP_EMC6D100_A1:
/* Note: we can't tell a '100 from a '101 */
kind = emc6d100;
break;
case LM85_VERSTEP_EMC6D102:
kind = emc6d102;
break;
} }
} else { break;
dev_dbg(&adapter->dev, "Autodetection failed: " }
"unknown vendor\n"); } else if (company == LM85_COMPANY_ANALOG_DEV) {
return -ENODEV; switch (verstep) {
case LM85_VERSTEP_ADM1027:
type_name = "adm1027";
break;
case LM85_VERSTEP_ADT7463:
case LM85_VERSTEP_ADT7463C:
type_name = "adt7463";
break;
case LM85_VERSTEP_ADT7468_1:
case LM85_VERSTEP_ADT7468_2:
type_name = "adt7468";
break;
} }
} else if (company == LM85_COMPANY_SMSC) {
switch (verstep) {
case LM85_VERSTEP_EMC6D100_A0:
case LM85_VERSTEP_EMC6D100_A1:
/* Note: we can't tell a '100 from a '101 */
type_name = "emc6d100";
break;
case LM85_VERSTEP_EMC6D102:
type_name = "emc6d102";
break;
}
} else {
dev_dbg(&adapter->dev,
"Autodetection failed: unknown vendor\n");
return -ENODEV;
} }
switch (kind) {
case lm85b:
type_name = "lm85b";
break;
case lm85c:
type_name = "lm85c";
break;
case adm1027:
type_name = "adm1027";
break;
case adt7463:
type_name = "adt7463";
break;
case adt7468:
type_name = "adt7468";
break;
case emc6d100:
type_name = "emc6d100";
break;
case emc6d102:
type_name = "emc6d102";
break;
default:
type_name = "lm85";
}
strlcpy(info->type, type_name, I2C_NAME_SIZE); strlcpy(info->type, type_name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -666,37 +666,32 @@ static int lm87_detect(struct i2c_client *new_client, int kind, ...@@ -666,37 +666,32 @@ static int lm87_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
static const char *names[] = { "lm87", "adm1024" }; const char *name;
u8 cid, rev;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* Default to an LM87 if forced */ if (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)
if (kind == 0) return -ENODEV;
kind = lm87;
/* Now, we do the remaining detection. */ /* Now, we do the remaining detection. */
if (kind < 0) { cid = lm87_read_value(new_client, LM87_REG_COMPANY_ID);
u8 cid = lm87_read_value(new_client, LM87_REG_COMPANY_ID); rev = lm87_read_value(new_client, LM87_REG_REVISION);
u8 rev = lm87_read_value(new_client, LM87_REG_REVISION);
if (cid == 0x02 /* National Semiconductor */
if (cid == 0x02 /* National Semiconductor */ && (rev >= 0x01 && rev <= 0x08))
&& (rev >= 0x01 && rev <= 0x08)) name = "lm87";
kind = lm87; else if (cid == 0x41 /* Analog Devices */
else if (cid == 0x41 /* Analog Devices */ && (rev & 0xf0) == 0x10)
&& (rev & 0xf0) == 0x10) name = "adm1024";
kind = adm1024; else {
dev_dbg(&adapter->dev, "LM87 detection failed at 0x%02x\n",
if (kind < 0 new_client->addr);
|| (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) { return -ENODEV;
dev_dbg(&adapter->dev,
"LM87 detection failed at 0x%02x.\n",
new_client->addr);
return -ENODEV;
}
} }
strlcpy(info->type, names[kind - 1], I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
} }
......
/* /*
* lm90.c - Part of lm_sensors, Linux kernel modules for hardware * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring * monitoring
* Copyright (C) 2003-2008 Jean Delvare <khali@linux-fr.org> * Copyright (C) 2003-2009 Jean Delvare <khali@linux-fr.org>
* *
* Based on the lm83 driver. The LM90 is a sensor chip made by National * Based on the lm83 driver. The LM90 is a sensor chip made by National
* Semiconductor. It reports up to two temperatures (its own plus up to * Semiconductor. It reports up to two temperatures (its own plus up to
...@@ -661,154 +661,118 @@ static int lm90_detect(struct i2c_client *new_client, int kind, ...@@ -661,154 +661,118 @@ static int lm90_detect(struct i2c_client *new_client, int kind,
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int address = new_client->addr; int address = new_client->addr;
const char *name = ""; const char *name = NULL;
int man_id, chip_id, reg_config1, reg_convrate;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* /* detection and identification */
* Now we do the remaining detection. A negative kind means that if ((man_id = i2c_smbus_read_byte_data(new_client,
* the driver was loaded with no force parameter (default), so we
* must both detect and identify the chip. A zero kind means that
* the driver was loaded with the force parameter, the detection
* step shall be skipped. A positive kind means that the driver
* was loaded with the force parameter and a given kind of chip is
* requested, so both the detection and the identification steps
* are skipped.
*/
/* Default to an LM90 if forced */
if (kind == 0)
kind = lm90;
if (kind < 0) { /* detection and identification */
int man_id, chip_id, reg_config1, reg_convrate;
if ((man_id = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_MAN_ID)) < 0 LM90_REG_R_MAN_ID)) < 0
|| (chip_id = i2c_smbus_read_byte_data(new_client, || (chip_id = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CHIP_ID)) < 0 LM90_REG_R_CHIP_ID)) < 0
|| (reg_config1 = i2c_smbus_read_byte_data(new_client, || (reg_config1 = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONFIG1)) < 0 LM90_REG_R_CONFIG1)) < 0
|| (reg_convrate = i2c_smbus_read_byte_data(new_client, || (reg_convrate = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONVRATE)) < 0) LM90_REG_R_CONVRATE)) < 0)
return -ENODEV;
if ((address == 0x4C || address == 0x4D)
&& man_id == 0x01) { /* National Semiconductor */
int reg_config2;
reg_config2 = i2c_smbus_read_byte_data(new_client,
LM90_REG_R_CONFIG2);
if (reg_config2 < 0)
return -ENODEV; return -ENODEV;
if ((address == 0x4C || address == 0x4D) if ((reg_config1 & 0x2A) == 0x00
&& man_id == 0x01) { /* National Semiconductor */ && (reg_config2 & 0xF8) == 0x00
int reg_config2; && reg_convrate <= 0x09) {
if (address == 0x4C
if ((reg_config2 = i2c_smbus_read_byte_data(new_client, && (chip_id & 0xF0) == 0x20) { /* LM90 */
LM90_REG_R_CONFIG2)) < 0) name = "lm90";
return -ENODEV;
if ((reg_config1 & 0x2A) == 0x00
&& (reg_config2 & 0xF8) == 0x00
&& reg_convrate <= 0x09) {
if (address == 0x4C
&& (chip_id & 0xF0) == 0x20) { /* LM90 */
kind = lm90;
} else
if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
kind = lm99;
dev_info(&adapter->dev,
"Assuming LM99 chip at "
"0x%02x\n", address);
dev_info(&adapter->dev,
"If it is an LM89, pass "
"force_lm86=%d,0x%02x when "
"loading the lm90 driver\n",
i2c_adapter_id(adapter),
address);
} else
if (address == 0x4C
&& (chip_id & 0xF0) == 0x10) { /* LM86 */
kind = lm86;
}
}
} else
if ((address == 0x4C || address == 0x4D)
&& man_id == 0x41) { /* Analog Devices */
if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
&& (reg_config1 & 0x3F) == 0x00
&& reg_convrate <= 0x0A) {
kind = adm1032;
} else
if (chip_id == 0x51 /* ADT7461 */
&& (reg_config1 & 0x1B) == 0x00
&& reg_convrate <= 0x0A) {
kind = adt7461;
}
} else
if (man_id == 0x4D) { /* Maxim */
/*
* The MAX6657, MAX6658 and MAX6659 do NOT have a
* chip_id register. Reading from that address will
* return the last read value, which in our case is
* those of the man_id register. Likewise, the config1
* register seems to lack a low nibble, so the value
* will be those of the previous read, so in our case
* those of the man_id register.
*/
if (chip_id == man_id
&& (address == 0x4C || address == 0x4D)
&& (reg_config1 & 0x1F) == (man_id & 0x0F)
&& reg_convrate <= 0x09) {
kind = max6657;
} else } else
/* The chip_id register of the MAX6680 and MAX6681 if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
* holds the revision of the chip. name = "lm99";
* the lowest bit of the config1 register is unused dev_info(&adapter->dev,
* and should return zero when read, so should the "Assuming LM99 chip at 0x%02x\n",
* second to last bit of config1 (software reset) address);
*/ dev_info(&adapter->dev,
if (chip_id == 0x01 "If it is an LM89, instantiate it "
&& (reg_config1 & 0x03) == 0x00 "with the new_device sysfs "
&& reg_convrate <= 0x07) { "interface\n");
kind = max6680;
} else } else
/* The chip_id register of the MAX6646/6647/6649 if (address == 0x4C
* holds the revision of the chip. && (chip_id & 0xF0) == 0x10) { /* LM86 */
* The lowest 6 bits of the config1 register are name = "lm86";
* unused and should return zero when read.
*/
if (chip_id == 0x59
&& (reg_config1 & 0x3f) == 0x00
&& reg_convrate <= 0x07) {
kind = max6646;
} }
} }
} else
if (kind <= 0) { /* identification failed */ if ((address == 0x4C || address == 0x4D)
dev_dbg(&adapter->dev, && man_id == 0x41) { /* Analog Devices */
"Unsupported chip at 0x%02x (man_id=0x%02X, " if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
"chip_id=0x%02X)\n", address, man_id, chip_id); && (reg_config1 & 0x3F) == 0x00
return -ENODEV; && reg_convrate <= 0x0A) {
name = "adm1032";
/* The ADM1032 supports PEC, but only if combined
transactions are not used. */
if (i2c_check_functionality(adapter,
I2C_FUNC_SMBUS_BYTE))
info->flags |= I2C_CLIENT_PEC;
} else
if (chip_id == 0x51 /* ADT7461 */
&& (reg_config1 & 0x1B) == 0x00
&& reg_convrate <= 0x0A) {
name = "adt7461";
}
} else
if (man_id == 0x4D) { /* Maxim */
/*
* The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id
* register. Reading from that address will return the last
* read value, which in our case is those of the man_id
* register. Likewise, the config1 register seems to lack a
* low nibble, so the value will be those of the previous
* read, so in our case those of the man_id register.
*/
if (chip_id == man_id
&& (address == 0x4C || address == 0x4D)
&& (reg_config1 & 0x1F) == (man_id & 0x0F)
&& reg_convrate <= 0x09) {
name = "max6657";
} else
/*
* The chip_id register of the MAX6680 and MAX6681 holds the
* revision of the chip. The lowest bit of the config1 register
* is unused and should return zero when read, so should the
* second to last bit of config1 (software reset).
*/
if (chip_id == 0x01
&& (reg_config1 & 0x03) == 0x00
&& reg_convrate <= 0x07) {
name = "max6680";
} else
/*
* The chip_id register of the MAX6646/6647/6649 holds the
* revision of the chip. The lowest 6 bits of the config1
* register are unused and should return zero when read.
*/
if (chip_id == 0x59
&& (reg_config1 & 0x3f) == 0x00
&& reg_convrate <= 0x07) {
name = "max6646";
} }
} }
/* Fill the i2c board info */ if (!name) { /* identification failed */
if (kind == lm90) { dev_dbg(&adapter->dev,
name = "lm90"; "Unsupported chip at 0x%02x (man_id=0x%02X, "
} else if (kind == adm1032) { "chip_id=0x%02X)\n", address, man_id, chip_id);
name = "adm1032"; return -ENODEV;
/* The ADM1032 supports PEC, but only if combined
transactions are not used. */
if (i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
info->flags |= I2C_CLIENT_PEC;
} else if (kind == lm99) {
name = "lm99";
} else if (kind == lm86) {
name = "lm86";
} else if (kind == max6657) {
name = "max6657";
} else if (kind == max6680) {
name = "max6680";
} else if (kind == adt7461) {
name = "adt7461";
} else if (kind == max6646) {
name = "max6646";
} }
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -323,31 +323,22 @@ static int lm92_detect(struct i2c_client *new_client, int kind, ...@@ -323,31 +323,22 @@ static int lm92_detect(struct i2c_client *new_client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
u8 config;
u16 man_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA)) | I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV; return -ENODEV;
/* A negative kind means that the driver was loaded with no force config = i2c_smbus_read_byte_data(new_client, LM92_REG_CONFIG);
parameter (default), so we must identify the chip. */ man_id = i2c_smbus_read_word_data(new_client, LM92_REG_MAN_ID);
if (kind < 0) {
u8 config = i2c_smbus_read_byte_data(new_client, if ((config & 0xe0) == 0x00 && man_id == 0x0180)
LM92_REG_CONFIG); pr_info("lm92: Found National Semiconductor LM92 chip\n");
u16 man_id = i2c_smbus_read_word_data(new_client, else if (max6635_check(new_client))
LM92_REG_MAN_ID); pr_info("lm92: Found Maxim MAX6635 chip\n");
else
if ((config & 0xe0) == 0x00 return -ENODEV;
&& man_id == 0x0180) {
pr_info("lm92: Found National Semiconductor LM92 chip\n");
kind = lm92;
} else
if (max6635_check(new_client)) {
pr_info("lm92: Found Maxim MAX6635 chip\n");
kind = lm92; /* No separate prefix */
}
else
return -ENODEV;
}
strlcpy(info->type, "lm92", I2C_NAME_SIZE); strlcpy(info->type, "lm92", I2C_NAME_SIZE);
......
...@@ -2505,34 +2505,24 @@ static int lm93_detect(struct i2c_client *client, int kind, ...@@ -2505,34 +2505,24 @@ static int lm93_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int mfr, ver;
if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN)) if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN))
return -ENODEV; return -ENODEV;
/* detection */ /* detection */
if (kind < 0) { mfr = lm93_read_byte(client, LM93_REG_MFR_ID);
int mfr = lm93_read_byte(client, LM93_REG_MFR_ID); if (mfr != 0x01) {
dev_dbg(&adapter->dev,
if (mfr != 0x01) { "detect failed, bad manufacturer id 0x%02x!\n", mfr);
dev_dbg(&adapter->dev,"detect failed, " return -ENODEV;
"bad manufacturer id 0x%02x!\n", mfr);
return -ENODEV;
}
} }
if (kind <= 0) { ver = lm93_read_byte(client, LM93_REG_VER);
int ver = lm93_read_byte(client, LM93_REG_VER); if (ver != LM93_MFR_ID && ver != LM93_MFR_ID_PROTOTYPE) {
dev_dbg(&adapter->dev,
if ((ver == LM93_MFR_ID) || (ver == LM93_MFR_ID_PROTOTYPE)) { "detect failed, bad version id 0x%02x!\n", ver);
kind = lm93; return -ENODEV;
} else {
dev_dbg(&adapter->dev,"detect failed, "
"bad version id 0x%02x!\n", ver);
if (kind == 0)
dev_dbg(&adapter->dev,
"(ignored 'force' parameter)\n");
return -ENODEV;
}
} }
strlcpy(info->type, "lm93", I2C_NAME_SIZE); strlcpy(info->type, "lm93", I2C_NAME_SIZE);
......
...@@ -315,51 +315,23 @@ static int lm95241_detect(struct i2c_client *new_client, int kind, ...@@ -315,51 +315,23 @@ static int lm95241_detect(struct i2c_client *new_client, int kind,
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int address = new_client->addr; int address = new_client->addr;
const char *name = ""; const char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
* Now we do the remaining detection. A negative kind means that == MANUFACTURER_ID)
* the driver was loaded with no force parameter (default), so we && (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
* must both detect and identify the chip. A zero kind means that >= DEFAULT_REVISION)) {
* the driver was loaded with the force parameter, the detection name = "lm95241";
* step shall be skipped. A positive kind means that the driver } else {
* was loaded with the force parameter and a given kind of chip is dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
* requested, so both the detection and the identification steps address);
* are skipped. return -ENODEV;
*/
if (kind < 0) { /* detection */
if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
!= MANUFACTURER_ID)
|| (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
< DEFAULT_REVISION)) {
dev_dbg(&adapter->dev,
"LM95241 detection failed at 0x%02x.\n",
address);
return -ENODEV;
}
}
if (kind <= 0) { /* identification */
if ((i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID)
== MANUFACTURER_ID)
&& (i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID)
>= DEFAULT_REVISION)) {
kind = lm95241;
if (kind <= 0) { /* identification failed */
dev_info(&adapter->dev, "Unsupported chip\n");
return -ENODEV;
}
}
} }
/* Fill the i2c board info */ /* Fill the i2c board info */
if (kind == lm95241)
name = "lm95241";
strlcpy(info->type, name, I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
} }
......
...@@ -226,58 +226,34 @@ static const struct attribute_group max1619_group = { ...@@ -226,58 +226,34 @@ static const struct attribute_group max1619_group = {
*/ */
/* Return 0 if detection is successful, -ENODEV otherwise */ /* Return 0 if detection is successful, -ENODEV otherwise */
static int max1619_detect(struct i2c_client *new_client, int kind, static int max1619_detect(struct i2c_client *client, int kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = client->adapter;
u8 reg_config=0, reg_convrate=0, reg_status=0; u8 reg_config, reg_convrate, reg_status, man_id, chip_id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* /* detection */
* Now we do the remaining detection. A negative kind means that reg_config = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONFIG);
* the driver was loaded with no force parameter (default), so we reg_convrate = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONVRATE);
* must both detect and identify the chip. A zero kind means that reg_status = i2c_smbus_read_byte_data(client, MAX1619_REG_R_STATUS);
* the driver was loaded with the force parameter, the detection if ((reg_config & 0x03) != 0x00
* step shall be skipped. A positive kind means that the driver || reg_convrate > 0x07 || (reg_status & 0x61) != 0x00) {
* was loaded with the force parameter and a given kind of chip is dev_dbg(&adapter->dev, "MAX1619 detection failed at 0x%02x\n",
* requested, so both the detection and the identification steps client->addr);
* are skipped. return -ENODEV;
*/
if (kind < 0) { /* detection */
reg_config = i2c_smbus_read_byte_data(new_client,
MAX1619_REG_R_CONFIG);
reg_convrate = i2c_smbus_read_byte_data(new_client,
MAX1619_REG_R_CONVRATE);
reg_status = i2c_smbus_read_byte_data(new_client,
MAX1619_REG_R_STATUS);
if ((reg_config & 0x03) != 0x00
|| reg_convrate > 0x07 || (reg_status & 0x61 ) !=0x00) {
dev_dbg(&adapter->dev,
"MAX1619 detection failed at 0x%02x.\n",
new_client->addr);
return -ENODEV;
}
} }
if (kind <= 0) { /* identification */ /* identification */
u8 man_id, chip_id; man_id = i2c_smbus_read_byte_data(client, MAX1619_REG_R_MAN_ID);
chip_id = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CHIP_ID);
man_id = i2c_smbus_read_byte_data(new_client, if (man_id != 0x4D || chip_id != 0x04) {
MAX1619_REG_R_MAN_ID); dev_info(&adapter->dev,
chip_id = i2c_smbus_read_byte_data(new_client, "Unsupported chip (man_id=0x%02X, chip_id=0x%02X).\n",
MAX1619_REG_R_CHIP_ID); man_id, chip_id);
return -ENODEV;
if ((man_id == 0x4D) && (chip_id == 0x04))
kind = max1619;
if (kind <= 0) { /* identification failed */
dev_info(&adapter->dev,
"Unsupported chip (man_id=0x%02X, "
"chip_id=0x%02X).\n", man_id, chip_id);
return -ENODEV;
}
} }
strlcpy(info->type, "max1619", I2C_NAME_SIZE); strlcpy(info->type, "max1619", I2C_NAME_SIZE);
......
...@@ -534,7 +534,7 @@ static int max6650_detect(struct i2c_client *client, int kind, ...@@ -534,7 +534,7 @@ static int max6650_detect(struct i2c_client *client, int kind,
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int address = client->addr; int address = client->addr;
dev_dbg(&adapter->dev, "max6650_detect called, kind = %d\n", kind); dev_dbg(&adapter->dev, "max6650_detect called\n");
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support " dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support "
...@@ -542,23 +542,7 @@ static int max6650_detect(struct i2c_client *client, int kind, ...@@ -542,23 +542,7 @@ static int max6650_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
} }
/* if (((i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0)
* Now we do the remaining detection. A negative kind means that
* the driver was loaded with no force parameter (default), so we
* must both detect and identify the chip (actually there is only
* one possible kind of chip for now, max6650). A zero kind means that
* the driver was loaded with the force parameter, the detection
* step shall be skipped. A positive kind means that the driver
* was loaded with the force parameter and a given kind of chip is
* requested, so both the detection and the identification steps
* are skipped.
*
* Currently I can find no way to distinguish between a MAX6650 and
* a MAX6651. This driver has only been tried on the former.
*/
if ((kind < 0) &&
( (i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG) & 0xC0)
||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0) ||(i2c_smbus_read_byte_data(client, MAX6650_REG_GPIO_STAT) & 0xE0)
||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0) ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN) & 0xE0)
||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0) ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0)
......
/*
* Driver for the Freescale Semiconductor MC13783 adc.
*
* Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
* Copyright (C) 2009 Sascha Hauer, Pengutronix
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the Free Software Foundation, Inc., 51
* Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <linux/mfd/mc13783-private.h>
#include <linux/platform_device.h>
#include <linux/hwmon-sysfs.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/hwmon.h>
#include <linux/init.h>
#include <linux/err.h>
#define MC13783_ADC_NAME "mc13783-adc"
struct mc13783_adc_priv {
struct mc13783 *mc13783;
struct device *hwmon_dev;
};
static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute
*devattr, char *buf)
{
return sprintf(buf, "mc13783_adc\n");
}
static int mc13783_adc_read(struct device *dev,
struct device_attribute *devattr, unsigned int *val)
{
struct platform_device *pdev = to_platform_device(dev);
struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
unsigned int channel = attr->index;
unsigned int sample[4];
int ret;
ret = mc13783_adc_do_conversion(priv->mc13783,
MC13783_ADC_MODE_MULT_CHAN,
channel, sample);
if (ret)
return ret;
channel &= 0x7;
*val = (sample[channel % 4] >> (channel > 3 ? 14 : 2)) & 0x3ff;
return 0;
}
static ssize_t mc13783_adc_read_bp(struct device *dev,
struct device_attribute *devattr, char *buf)
{
unsigned val;
int ret = mc13783_adc_read(dev, devattr, &val);
if (ret)
return ret;
/*
* BP (channel 2) reports with offset 2.4V to the actual value to fit
* the input range of the ADC. unit = 2.25mV = 9/4 mV.
*/
val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400;
return sprintf(buf, "%u\n", val);
}
static ssize_t mc13783_adc_read_gp(struct device *dev,
struct device_attribute *devattr, char *buf)
{
unsigned val;
int ret = mc13783_adc_read(dev, devattr, &val);
if (ret)
return ret;
/*
* input range is [0, 2.3V], val has 10 bits, so each bit
* is worth 9/4 mV.
*/
val = DIV_ROUND_CLOSEST(val * 9, 4);
return sprintf(buf, "%u\n", val);
}
static DEVICE_ATTR(name, S_IRUGO, mc13783_adc_show_name, NULL);
static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read_bp, NULL, 2);
static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read_gp, NULL, 5);
static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, mc13783_adc_read_gp, NULL, 6);
static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, mc13783_adc_read_gp, NULL, 7);
static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, mc13783_adc_read_gp, NULL, 8);
static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, mc13783_adc_read_gp, NULL, 9);
static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, mc13783_adc_read_gp, NULL, 10);
static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, mc13783_adc_read_gp, NULL, 11);
static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read_gp, NULL, 12);
static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13);
static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14);
static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15);
static struct attribute *mc13783_attr[] = {
&dev_attr_name.attr,
&sensor_dev_attr_in2_input.dev_attr.attr,
&sensor_dev_attr_in5_input.dev_attr.attr,
&sensor_dev_attr_in6_input.dev_attr.attr,
&sensor_dev_attr_in7_input.dev_attr.attr,
&sensor_dev_attr_in8_input.dev_attr.attr,
&sensor_dev_attr_in9_input.dev_attr.attr,
&sensor_dev_attr_in10_input.dev_attr.attr,
&sensor_dev_attr_in11_input.dev_attr.attr,
NULL
};
static const struct attribute_group mc13783_group = {
.attrs = mc13783_attr,
};
/* last four channels may be occupied by the touchscreen */
static struct attribute *mc13783_attr_ts[] = {
&sensor_dev_attr_in12_input.dev_attr.attr,
&sensor_dev_attr_in13_input.dev_attr.attr,
&sensor_dev_attr_in14_input.dev_attr.attr,
&sensor_dev_attr_in15_input.dev_attr.attr,
NULL
};
static const struct attribute_group mc13783_group_ts = {
.attrs = mc13783_attr_ts,
};
static int __init mc13783_adc_probe(struct platform_device *pdev)
{
struct mc13783_adc_priv *priv;
int ret;
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
if (!priv)
return -ENOMEM;
priv->mc13783 = dev_get_drvdata(pdev->dev.parent);
platform_set_drvdata(pdev, priv);
/* Register sysfs hooks */
ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group);
if (ret)
goto out_err_create1;
if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN))
ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts);
if (ret)
goto out_err_create2;
priv->hwmon_dev = hwmon_device_register(&pdev->dev);
if (IS_ERR(priv->hwmon_dev)) {
ret = PTR_ERR(priv->hwmon_dev);
dev_err(&pdev->dev,
"hwmon_device_register failed with %d.\n", ret);
goto out_err_register;
}
return 0;
out_err_register:
if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN))
sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
out_err_create2:
sysfs_remove_group(&pdev->dev.kobj, &mc13783_group);
out_err_create1:
platform_set_drvdata(pdev, NULL);
kfree(priv);
return ret;
}
static int __devexit mc13783_adc_remove(struct platform_device *pdev)
{
struct mc13783_adc_priv *priv = platform_get_drvdata(pdev);
hwmon_device_unregister(priv->hwmon_dev);
if (!(priv->mc13783->flags & MC13783_USE_TOUCHSCREEN))
sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts);
sysfs_remove_group(&pdev->dev.kobj, &mc13783_group);
platform_set_drvdata(pdev, NULL);
kfree(priv);
return 0;
}
static struct platform_driver mc13783_adc_driver = {
.remove = __devexit_p(mc13783_adc_remove),
.driver = {
.owner = THIS_MODULE,
.name = MC13783_ADC_NAME,
},
};
static int __init mc13783_adc_init(void)
{
return platform_driver_probe(&mc13783_adc_driver, mc13783_adc_probe);
}
static void __exit mc13783_adc_exit(void)
{
platform_driver_unregister(&mc13783_adc_driver);
}
module_init(mc13783_adc_init);
module_exit(mc13783_adc_exit);
MODULE_DESCRIPTION("MC13783 ADC driver");
MODULE_AUTHOR("Luotao Fu <l.fu@pengutronix.de>");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" MC13783_ADC_NAME);
...@@ -323,7 +323,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev) ...@@ -323,7 +323,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev)
} }
for (i = 0; i < ARRAY_SIZE(pdata->in); i++) { for (i = 0; i < ARRAY_SIZE(pdata->in); i++) {
struct s3c24xx_adc_hwmon_incfg *cfg = pdata->in[i]; struct s3c_hwmon_chcfg *cfg = pdata->in[i];
if (!cfg) if (!cfg)
continue; continue;
...@@ -333,7 +333,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev) ...@@ -333,7 +333,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev)
"channel %d multiplier too large\n", "channel %d multiplier too large\n",
i); i);
if (cfg->divider == 0) { if (cfg->div == 0) {
dev_err(&dev->dev, "channel %d divider zero\n", i); dev_err(&dev->dev, "channel %d divider zero\n", i);
continue; continue;
} }
......
...@@ -491,24 +491,22 @@ static int smsc47m192_detect(struct i2c_client *client, int kind, ...@@ -491,24 +491,22 @@ static int smsc47m192_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
/* Detection criteria from sensors_detect script */ /* Detection criteria from sensors_detect script */
if (kind < 0) { version = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VERSION);
if (i2c_smbus_read_byte_data(client, if (i2c_smbus_read_byte_data(client,
SMSC47M192_REG_COMPANY_ID) == 0x55 SMSC47M192_REG_COMPANY_ID) == 0x55
&& ((version = i2c_smbus_read_byte_data(client, && (version & 0xf0) == 0x20
SMSC47M192_REG_VERSION)) & 0xf0) == 0x20 && (i2c_smbus_read_byte_data(client,
&& (i2c_smbus_read_byte_data(client,
SMSC47M192_REG_VID) & 0x70) == 0x00 SMSC47M192_REG_VID) & 0x70) == 0x00
&& (i2c_smbus_read_byte_data(client, && (i2c_smbus_read_byte_data(client,
SMSC47M192_REG_VID4) & 0xfe) == 0x80) { SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
dev_info(&adapter->dev, dev_info(&adapter->dev,
"found SMSC47M192 or compatible, " "found SMSC47M192 or compatible, "
"version 2, stepping A%d\n", version & 0x0f); "version 2, stepping A%d\n", version & 0x0f);
} else { } else {
dev_dbg(&adapter->dev, dev_dbg(&adapter->dev,
"SMSC47M192 detection failed at 0x%02x\n", "SMSC47M192 detection failed at 0x%02x\n",
client->addr); client->addr);
return -ENODEV; return -ENODEV;
}
} }
strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE); strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE);
......
...@@ -36,7 +36,11 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; ...@@ -36,7 +36,11 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
/* Insmod parameters */ /* Insmod parameters */
I2C_CLIENT_INSMOD_2(thmc50, adm1022); I2C_CLIENT_INSMOD_2(thmc50, adm1022);
I2C_CLIENT_MODULE_PARM(adm1022_temp3, "List of adapter,address pairs "
static unsigned short adm1022_temp3[16];
static unsigned int adm1022_temp3_num;
module_param_array(adm1022_temp3, ushort, &adm1022_temp3_num, 0);
MODULE_PARM_DESC(adm1022_temp3, "List of adapter,address pairs "
"to enable 3rd temperature (ADM1022 only)"); "to enable 3rd temperature (ADM1022 only)");
/* Many THMC50 constants specified below */ /* Many THMC50 constants specified below */
...@@ -289,7 +293,6 @@ static int thmc50_detect(struct i2c_client *client, int kind, ...@@ -289,7 +293,6 @@ static int thmc50_detect(struct i2c_client *client, int kind,
unsigned revision; unsigned revision;
unsigned config; unsigned config;
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int err = 0;
const char *type_name; const char *type_name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
...@@ -301,31 +304,13 @@ static int thmc50_detect(struct i2c_client *client, int kind, ...@@ -301,31 +304,13 @@ static int thmc50_detect(struct i2c_client *client, int kind,
pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n",
client->addr, i2c_adapter_id(client->adapter)); client->addr, i2c_adapter_id(client->adapter));
/* Now, we do the remaining detection. */
company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID); company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID);
revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE); revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE);
config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
if (revision < 0xc0 || (config & 0x10))
return -ENODEV;
if (kind == 0) if (company == 0x41) {
kind = thmc50;
else if (kind < 0) {
err = -ENODEV;
if (revision >= 0xc0 && ((config & 0x10) == 0)) {
if (company == 0x49) {
kind = thmc50;
err = 0;
} else if (company == 0x41) {
kind = adm1022;
err = 0;
}
}
}
if (err == -ENODEV) {
pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n");
return err;
}
if (kind == adm1022) {
int id = i2c_adapter_id(client->adapter); int id = i2c_adapter_id(client->adapter);
int i; int i;
...@@ -340,9 +325,13 @@ static int thmc50_detect(struct i2c_client *client, int kind, ...@@ -340,9 +325,13 @@ static int thmc50_detect(struct i2c_client *client, int kind,
config); config);
break; break;
} }
} else { } else if (company == 0x49) {
type_name = "thmc50"; type_name = "thmc50";
} else {
pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n");
return -ENODEV;
} }
pr_debug("thmc50: Detected %s (version %x, revision %x)\n", pr_debug("thmc50: Detected %s (version %x, revision %x)\n",
type_name, (revision >> 4) - 0xc, revision & 0xf); type_name, (revision >> 4) - 0xc, revision & 0xf);
......
...@@ -488,46 +488,43 @@ static void tmp401_init_client(struct i2c_client *client) ...@@ -488,46 +488,43 @@ static void tmp401_init_client(struct i2c_client *client)
i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config); i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config);
} }
static int tmp401_detect(struct i2c_client *client, int kind, static int tmp401_detect(struct i2c_client *client, int _kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
enum chips kind;
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
u8 reg;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
/* Detect and identify the chip */ /* Detect and identify the chip */
if (kind <= 0) { reg = i2c_smbus_read_byte_data(client, TMP401_MANUFACTURER_ID_REG);
u8 reg; if (reg != TMP401_MANUFACTURER_ID)
return -ENODEV;
reg = i2c_smbus_read_byte_data(client,
TMP401_MANUFACTURER_ID_REG);
if (reg != TMP401_MANUFACTURER_ID)
return -ENODEV;
reg = i2c_smbus_read_byte_data(client, TMP401_DEVICE_ID_REG);
switch (reg) {
case TMP401_DEVICE_ID:
kind = tmp401;
break;
case TMP411_DEVICE_ID:
kind = tmp411;
break;
default:
return -ENODEV;
}
reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); reg = i2c_smbus_read_byte_data(client, TMP401_DEVICE_ID_REG);
if (reg & 0x1b)
return -ENODEV;
reg = i2c_smbus_read_byte_data(client, switch (reg) {
TMP401_CONVERSION_RATE_READ); case TMP401_DEVICE_ID:
/* Datasheet says: 0x1-0x6 */ kind = tmp401;
if (reg > 15) break;
return -ENODEV; case TMP411_DEVICE_ID:
kind = tmp411;
break;
default:
return -ENODEV;
} }
reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
if (reg & 0x1b)
return -ENODEV;
reg = i2c_smbus_read_byte_data(client, TMP401_CONVERSION_RATE_READ);
/* Datasheet says: 0x1-0x6 */
if (reg > 15)
return -ENODEV;
strlcpy(info->type, tmp401_id[kind - 1].name, I2C_NAME_SIZE); strlcpy(info->type, tmp401_id[kind - 1].name, I2C_NAME_SIZE);
return 0; return 0;
......
...@@ -223,39 +223,36 @@ static int tmp421_init_client(struct i2c_client *client) ...@@ -223,39 +223,36 @@ static int tmp421_init_client(struct i2c_client *client)
return 0; return 0;
} }
static int tmp421_detect(struct i2c_client *client, int kind, static int tmp421_detect(struct i2c_client *client, int _kind,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
enum chips kind;
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
const char *names[] = { "TMP421", "TMP422", "TMP423" }; const char *names[] = { "TMP421", "TMP422", "TMP423" };
u8 reg;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (kind <= 0) { reg = i2c_smbus_read_byte_data(client, TMP421_MANUFACTURER_ID_REG);
u8 reg; if (reg != TMP421_MANUFACTURER_ID)
return -ENODEV;
reg = i2c_smbus_read_byte_data(client,
TMP421_MANUFACTURER_ID_REG); reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG);
if (reg != TMP421_MANUFACTURER_ID) switch (reg) {
return -ENODEV; case TMP421_DEVICE_ID:
kind = tmp421;
reg = i2c_smbus_read_byte_data(client, break;
TMP421_DEVICE_ID_REG); case TMP422_DEVICE_ID:
switch (reg) { kind = tmp422;
case TMP421_DEVICE_ID: break;
kind = tmp421; case TMP423_DEVICE_ID:
break; kind = tmp423;
case TMP422_DEVICE_ID: break;
kind = tmp422; default:
break; return -ENODEV;
case TMP423_DEVICE_ID:
kind = tmp423;
break;
default:
return -ENODEV;
}
} }
strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE); strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE);
dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n", dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",
names[kind - 1], client->addr); names[kind - 1], client->addr);
......
...@@ -59,10 +59,11 @@ static struct platform_device *pdev; ...@@ -59,10 +59,11 @@ static struct platform_device *pdev;
#define DRVNAME "w83627hf" #define DRVNAME "w83627hf"
enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
static u16 force_addr; struct w83627hf_sio_data {
module_param(force_addr, ushort, 0); enum chips type;
MODULE_PARM_DESC(force_addr, int sioaddr;
"Initialize the base address of the sensors"); };
static u8 force_i2c = 0x1f; static u8 force_i2c = 0x1f;
module_param(force_i2c, byte, 0); module_param(force_i2c, byte, 0);
MODULE_PARM_DESC(force_i2c, MODULE_PARM_DESC(force_i2c,
...@@ -77,9 +78,7 @@ module_param(force_id, ushort, 0); ...@@ -77,9 +78,7 @@ module_param(force_id, ushort, 0);
MODULE_PARM_DESC(force_id, "Override the detected device ID"); MODULE_PARM_DESC(force_id, "Override the detected device ID");
/* modified from kernel/include/traps.c */ /* modified from kernel/include/traps.c */
static int REG; /* The register to read/write */
#define DEV 0x07 /* Register: Logical device select */ #define DEV 0x07 /* Register: Logical device select */
static int VAL; /* The value to read/write */
/* logical device numbers for superio_select (below) */ /* logical device numbers for superio_select (below) */
#define W83627HF_LD_FDC 0x00 #define W83627HF_LD_FDC 0x00
...@@ -109,37 +108,37 @@ static int VAL; /* The value to read/write */ ...@@ -109,37 +108,37 @@ static int VAL; /* The value to read/write */
#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ #define W83687THF_VID_DATA 0xF1 /* w83687thf only */
static inline void static inline void
superio_outb(int reg, int val) superio_outb(struct w83627hf_sio_data *sio, int reg, int val)
{ {
outb(reg, REG); outb(reg, sio->sioaddr);
outb(val, VAL); outb(val, sio->sioaddr + 1);
} }
static inline int static inline int
superio_inb(int reg) superio_inb(struct w83627hf_sio_data *sio, int reg)
{ {
outb(reg, REG); outb(reg, sio->sioaddr);
return inb(VAL); return inb(sio->sioaddr + 1);
} }
static inline void static inline void
superio_select(int ld) superio_select(struct w83627hf_sio_data *sio, int ld)
{ {
outb(DEV, REG); outb(DEV, sio->sioaddr);
outb(ld, VAL); outb(ld, sio->sioaddr + 1);
} }
static inline void static inline void
superio_enter(void) superio_enter(struct w83627hf_sio_data *sio)
{ {
outb(0x87, REG); outb(0x87, sio->sioaddr);
outb(0x87, REG); outb(0x87, sio->sioaddr);
} }
static inline void static inline void
superio_exit(void) superio_exit(struct w83627hf_sio_data *sio)
{ {
outb(0xAA, REG); outb(0xAA, sio->sioaddr);
} }
#define W627_DEVID 0x52 #define W627_DEVID 0x52
...@@ -380,10 +379,6 @@ struct w83627hf_data { ...@@ -380,10 +379,6 @@ struct w83627hf_data {
u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */
}; };
struct w83627hf_sio_data {
enum chips type;
};
static int w83627hf_probe(struct platform_device *pdev); static int w83627hf_probe(struct platform_device *pdev);
static int __devexit w83627hf_remove(struct platform_device *pdev); static int __devexit w83627hf_remove(struct platform_device *pdev);
...@@ -1140,11 +1135,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, ...@@ -1140,11 +1135,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
"W83687THF", "W83687THF",
}; };
REG = sioaddr; superio_enter(sio_data);
VAL = sioaddr + 1; val = force_id ? force_id : superio_inb(sio_data, DEVID);
superio_enter();
val = force_id ? force_id : superio_inb(DEVID);
switch (val) { switch (val) {
case W627_DEVID: case W627_DEVID:
sio_data->type = w83627hf; sio_data->type = w83627hf;
...@@ -1168,16 +1160,9 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, ...@@ -1168,16 +1160,9 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
goto exit; goto exit;
} }
superio_select(W83627HF_LD_HWM); superio_select(sio_data, W83627HF_LD_HWM);
force_addr &= WINB_ALIGNMENT; val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
if (force_addr) { superio_inb(sio_data, WINB_BASE_REG + 1);
printk(KERN_WARNING DRVNAME ": Forcing address 0x%x\n",
force_addr);
superio_outb(WINB_BASE_REG, force_addr >> 8);
superio_outb(WINB_BASE_REG + 1, force_addr & 0xff);
}
val = (superio_inb(WINB_BASE_REG) << 8) |
superio_inb(WINB_BASE_REG + 1);
*addr = val & WINB_ALIGNMENT; *addr = val & WINB_ALIGNMENT;
if (*addr == 0) { if (*addr == 0) {
printk(KERN_WARNING DRVNAME ": Base address not set, " printk(KERN_WARNING DRVNAME ": Base address not set, "
...@@ -1185,18 +1170,19 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr, ...@@ -1185,18 +1170,19 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
goto exit; goto exit;
} }
val = superio_inb(WINB_ACT_REG); val = superio_inb(sio_data, WINB_ACT_REG);
if (!(val & 0x01)) { if (!(val & 0x01)) {
printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n"); printk(KERN_WARNING DRVNAME ": Enabling HWM logical device\n");
superio_outb(WINB_ACT_REG, val | 0x01); superio_outb(sio_data, WINB_ACT_REG, val | 0x01);
} }
err = 0; err = 0;
sio_data->sioaddr = sioaddr;
pr_info(DRVNAME ": Found %s chip at %#x\n", pr_info(DRVNAME ": Found %s chip at %#x\n",
names[sio_data->type], *addr); names[sio_data->type], *addr);
exit: exit:
superio_exit(); superio_exit(sio_data);
return err; return err;
} }
...@@ -1511,20 +1497,21 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) ...@@ -1511,20 +1497,21 @@ static int w83627hf_read_value(struct w83627hf_data *data, u16 reg)
static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
{ {
struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
int res = 0xff, sel; int res = 0xff, sel;
superio_enter(); superio_enter(sio_data);
superio_select(W83627HF_LD_GPIO5); superio_select(sio_data, W83627HF_LD_GPIO5);
/* Make sure these GPIO pins are enabled */ /* Make sure these GPIO pins are enabled */
if (!(superio_inb(W83627THF_GPIO5_EN) & (1<<3))) { if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) {
dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n");
goto exit; goto exit;
} }
/* Make sure the pins are configured for input /* Make sure the pins are configured for input
There must be at least five (VRM 9), and possibly 6 (VRM 10) */ There must be at least five (VRM 9), and possibly 6 (VRM 10) */
sel = superio_inb(W83627THF_GPIO5_IOSR) & 0x3f; sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f;
if ((sel & 0x1f) != 0x1f) { if ((sel & 0x1f) != 0x1f) {
dev_dbg(&pdev->dev, "GPIO5 not configured for VID " dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
"function\n"); "function\n");
...@@ -1532,37 +1519,38 @@ static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) ...@@ -1532,37 +1519,38 @@ static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
} }
dev_info(&pdev->dev, "Reading VID from GPIO5\n"); dev_info(&pdev->dev, "Reading VID from GPIO5\n");
res = superio_inb(W83627THF_GPIO5_DR) & sel; res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel;
exit: exit:
superio_exit(); superio_exit(sio_data);
return res; return res;
} }
static int __devinit w83687thf_read_vid(struct platform_device *pdev) static int __devinit w83687thf_read_vid(struct platform_device *pdev)
{ {
struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
int res = 0xff; int res = 0xff;
superio_enter(); superio_enter(sio_data);
superio_select(W83627HF_LD_HWM); superio_select(sio_data, W83627HF_LD_HWM);
/* Make sure these GPIO pins are enabled */ /* Make sure these GPIO pins are enabled */
if (!(superio_inb(W83687THF_VID_EN) & (1 << 2))) { if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) {
dev_dbg(&pdev->dev, "VID disabled, no VID function\n"); dev_dbg(&pdev->dev, "VID disabled, no VID function\n");
goto exit; goto exit;
} }
/* Make sure the pins are configured for input */ /* Make sure the pins are configured for input */
if (!(superio_inb(W83687THF_VID_CFG) & (1 << 4))) { if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) {
dev_dbg(&pdev->dev, "VID configured as output, " dev_dbg(&pdev->dev, "VID configured as output, "
"no VID function\n"); "no VID function\n");
goto exit; goto exit;
} }
res = superio_inb(W83687THF_VID_DATA) & 0x3f; res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
exit: exit:
superio_exit(); superio_exit(sio_data);
return res; return res;
} }
......
此差异已折叠。
...@@ -1270,56 +1270,32 @@ static int w83791d_detect(struct i2c_client *client, int kind, ...@@ -1270,56 +1270,32 @@ static int w83791d_detect(struct i2c_client *client, int kind,
return -ENODEV; return -ENODEV;
} }
/* The w83791d may be stuck in some other bank than bank 0. This may if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80)
make reading other information impossible. Specify a force=... return -ENODEV;
parameter, and the Winbond will be reset to the right bank. */
if (kind < 0) { val1 = w83791d_read(client, W83791D_REG_BANK);
if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) { val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
return -ENODEV; /* Check for Winbond ID if in bank 0 */
} if (!(val1 & 0x07)) {
val1 = w83791d_read(client, W83791D_REG_BANK); if ((!(val1 & 0x80) && val2 != 0xa3) ||
val2 = w83791d_read(client, W83791D_REG_CHIPMAN); ( (val1 & 0x80) && val2 != 0x5c)) {
/* Check for Winbond ID if in bank 0 */
if (!(val1 & 0x07)) {
/* yes it is Bank0 */
if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
((val1 & 0x80) && (val2 != 0x5c))) {
return -ENODEV;
}
}
/* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
should match */
if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) {
return -ENODEV; return -ENODEV;
} }
} }
/* If Winbond chip, address of chip and W83791D_REG_I2C_ADDR
should match */
if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address)
return -ENODEV;
/* We either have a force parameter or we have reason to /* We want bank 0 and Vendor ID high byte */
believe it is a Winbond chip. Either way, we want bank 0 and
Vendor ID high byte */
val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78; val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78;
w83791d_write(client, W83791D_REG_BANK, val1 | 0x80); w83791d_write(client, W83791D_REG_BANK, val1 | 0x80);
/* Verify it is a Winbond w83791d */ /* Verify it is a Winbond w83791d */
if (kind <= 0) { val1 = w83791d_read(client, W83791D_REG_WCHIPID);
/* get vendor ID */ val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
val2 = w83791d_read(client, W83791D_REG_CHIPMAN); if (val1 != 0x71 || val2 != 0x5c)
if (val2 != 0x5c) { /* the vendor is NOT Winbond */ return -ENODEV;
return -ENODEV;
}
val1 = w83791d_read(client, W83791D_REG_WCHIPID);
if (val1 == 0x71) {
kind = w83791d;
} else {
if (kind == 0)
dev_warn(&adapter->dev,
"w83791d: Ignoring 'force' parameter "
"for unknown chip at adapter %d, "
"address 0x%02x\n",
i2c_adapter_id(adapter), address);
return -ENODEV;
}
}
strlcpy(info->type, "w83791d", I2C_NAME_SIZE); strlcpy(info->type, "w83791d", I2C_NAME_SIZE);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册