Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelv...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 10 Dec 2009 03:53:11 +0000 (19:53 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 10 Dec 2009 03:53:11 +0000 (19:53 -0800)
* '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
  ...

58 files changed:
Documentation/feature-removal-schedule.txt
Documentation/hwmon/adt7473
Documentation/hwmon/adt7475
Documentation/hwmon/f71882fg
Documentation/hwmon/it87
Documentation/hwmon/mc13783-adc [new file with mode: 0644]
Documentation/hwmon/sysfs-interface
Documentation/hwmon/w83627hf
MAINTAINERS
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/adm1021.c
drivers/hwmon/adm1025.c
drivers/hwmon/adm1026.c
drivers/hwmon/adm1029.c
drivers/hwmon/adm1031.c
drivers/hwmon/adm9240.c
drivers/hwmon/ads7828.c
drivers/hwmon/adt7462.c
drivers/hwmon/adt7470.c
drivers/hwmon/adt7473.c
drivers/hwmon/adt7475.c
drivers/hwmon/asb100.c
drivers/hwmon/dme1737.c
drivers/hwmon/ds1621.c
drivers/hwmon/f71882fg.c
drivers/hwmon/f75375s.c
drivers/hwmon/fschmd.c
drivers/hwmon/gl518sm.c
drivers/hwmon/gl520sm.c
drivers/hwmon/it87.c
drivers/hwmon/lm63.c
drivers/hwmon/lm73.c [new file with mode: 0644]
drivers/hwmon/lm75.c
drivers/hwmon/lm77.c
drivers/hwmon/lm78.c
drivers/hwmon/lm83.c
drivers/hwmon/lm85.c
drivers/hwmon/lm87.c
drivers/hwmon/lm90.c
drivers/hwmon/lm92.c
drivers/hwmon/lm93.c
drivers/hwmon/lm95241.c
drivers/hwmon/max1619.c
drivers/hwmon/max6650.c
drivers/hwmon/mc13783-adc.c [new file with mode: 0644]
drivers/hwmon/s3c-hwmon.c
drivers/hwmon/smsc47m192.c
drivers/hwmon/thmc50.c
drivers/hwmon/tmp401.c
drivers/hwmon/tmp421.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/hwmon/w83791d.c
drivers/hwmon/w83792d.c
drivers/hwmon/w83793.c
drivers/hwmon/w83l785ts.c
drivers/hwmon/w83l786ng.c

index 591e94448e636edebab3791bdd69363b54a13895..2a4d77946c7dc075df1a6678a54204ea8e618502 100644 (file)
@@ -483,3 +483,10 @@ Why:       With the recent innovations in CPU hardware acceleration technologies
 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>
+
+---------------------------
index 1cbf671822e23d063c648984c145149792978c62..446612bd1fb983510dc67f2bbef51d2ee775b31d 100644 (file)
@@ -9,6 +9,8 @@ Supported chips:
 
 Author: Darrick J. Wong
 
+This driver is depreacted, please use the adt7475 driver instead.
+
 Description
 -----------
 
index a2b1abec850e7af2c2a524cd99b4c1ca83f96e9d..0502f2b464e1c09ec15a2cb4b9c9b3587419bb76 100644 (file)
-This describes the interface for the ADT7475 driver:
-
-(there are 4 fans, numbered fan1 to fan4):
-
-fanX_input             Read the current speed of the fan (in RPMs)
-fanX_min               Read/write the minimum speed of the fan.  Dropping
-                       below this sets an alarm.
-
-(there are three PWMs, numbered pwm1 to pwm3):
-
-pwmX                   Read/write the current duty cycle of the PWM.  Writes
-                       only have effect when auto mode is turned off (see
-                       below).  Range is 0 - 255.
-
-pwmX_enable            Fan speed control method:
-
-                       0 - No control (fan at full speed)
-                       1 - Manual fan speed control (using pwm[1-*])
-                       2 - Automatic fan speed control
-
-pwmX_auto_channels_temp        Select which channels affect this PWM
-
-                       1 - TEMP1 controls PWM
-                       2 - TEMP2 controls PWM
-                       4 - TEMP3 controls PWM
-                       6 - TEMP2 and TEMP3 control PWM
-                       7 - All three inputs control PWM
-
-pwmX_freq              Read/write the PWM frequency in Hz. The number
-                       should be one of the following:
-
-                       11 Hz
-                       14 Hz
-                       22 Hz
-                       29 Hz
-                       35 Hz
-                       44 Hz
-                       58 Hz
-                       88 Hz
-
-pwmX_auto_point1_pwm   Read/write the minimum PWM duty cycle in automatic mode
-
-pwmX_auto_point2_pwm   Read/write the maximum PWM duty cycle in automatic mode
-
-(there are three temperature settings numbered temp1 to temp3):
-
-tempX_input            Read the current temperature.  The value is in milli
-                       degrees of Celsius.
-
-tempX_max              Read/write the upper temperature limit - exceeding this
-                       will cause an alarm.
-
-tempX_min              Read/write the lower temperature limit - exceeding this
-                       will cause an alarm.
-
-tempX_offset           Read/write the temperature adjustment offset
-
-tempX_crit             Read/write the THERM limit for remote1.
-
-tempX_crit_hyst                Set the temperature value below crit where the
-                       fans will stay on - this helps drive the temperature
-                       low enough so it doesn't stay near the edge and
-                       cause THERM to keep tripping.
-
-tempX_auto_point1_temp Read/write the minimum temperature where the fans will
-                       turn on in automatic mode.
-
-tempX_auto_point2_temp Read/write the maximum temperature over which the fans
-                       will run in automatic mode.  tempX_auto_point1_temp
-                       and tempX_auto_point2_temp together define the
-                       range of automatic control.
-
-tempX_alarm            Read a 1 if the max/min alarm is set
-tempX_fault            Read a 1 if either temp1 or temp3 diode has a fault
-
-(There are two voltage settings, in1 and in2):
-
-inX_input              Read the current voltage on VCC.  Value is in
-                       millivolts.
-
-inX_min                        read/write the minimum voltage limit.
-                       Dropping below this causes an alarm.
-
-inX_max                        read/write the maximum voltage limit.
-                       Exceeding this causes an alarm.
-
-inX_alarm              Read a 1 if the max/min alarm is set.
+Kernel driver adt7475
+=====================
+
+Supported chips:
+  * Analog Devices ADT7473
+    Prefix: 'adt7473'
+    Addresses scanned: I2C 0x2C, 0x2D, 0x2E
+    Datasheet: Publicly available at the On Semiconductors website
+  * Analog Devices ADT7475
+    Prefix: 'adt7475'
+    Addresses scanned: I2C 0x2E
+    Datasheet: Publicly available at the On Semiconductors website
+  * Analog Devices ADT7476
+    Prefix: 'adt7476'
+    Addresses scanned: I2C 0x2C, 0x2D, 0x2E
+    Datasheet: Publicly available at the On Semiconductors website
+  * Analog Devices ADT7490
+    Prefix: 'adt7490'
+    Addresses scanned: I2C 0x2C, 0x2D, 0x2E
+    Datasheet: Publicly available at the On Semiconductors website
+
+Authors:
+       Jordan Crouse
+       Hans de Goede
+       Darrick J. Wong (documentation)
+       Jean Delvare
+
+
+Description
+-----------
+
+This driver implements support for the Analog Devices ADT7473, ADT7475,
+ADT7476 and ADT7490 chip family. The ADT7473 and ADT7475 differ only in
+minor details. The ADT7476 has additional features, including extra voltage
+measurement inputs and VID support. The ADT7490 also has additional
+features, including extra voltage measurement inputs and PECI support. All
+the supported chips will be collectively designed by the name "ADT747x" in
+the rest of this document.
+
+The ADT747x uses the 2-wire interface compatible with the SMBus 2.0
+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
+for measuring fan speed. There are three (3) PWM outputs that can be used
+to control fan speed.
+
+A sophisticated control system for the PWM outputs is designed into the
+ADT747x that allows fan speed to be adjusted automatically based on any of the
+three temperature sensors. Each PWM output is individually adjustable and
+programmable. Once configured, the ADT747x will adjust the PWM outputs in
+response to the measured temperatures without further host intervention.
+This feature can also be disabled for manual control of the PWM's.
+
+Each of the measured inputs (voltage, temperature, fan speed) has
+corresponding high/low limit values. The ADT747x will signal an ALARM if
+any measured value exceeds either limit.
+
+The ADT747x samples all inputs continuously. The driver will not read
+the registers more often than once every other second. Further,
+configuration data is only read once per minute.
+
+Chip Differences Summary
+------------------------
+
+ADT7473:
+  * 2 voltage inputs
+  * system acoustics optimizations (not implemented)
+
+ADT7475:
+  * 2 voltage inputs
+
+ADT7476:
+  * 5 voltage inputs
+  * VID support
+
+ADT7490:
+  * 6 voltage inputs
+  * 1 Imon input (not implemented)
+  * PECI support (not implemented)
+  * 2 GPIO pins (not implemented)
+  * system acoustics optimizations (not implemented)
+
+Special Features
+----------------
+
+The ADT747x has a 10-bit ADC and can therefore measure temperatures
+with a resolution of 0.25 degree Celsius. Temperature readings can be
+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.
index bee4c30bc1e2a82caa2421c9504e031ff1658c73..a7952c2bd959338d4358a8fbdb51ee80c62fa61d 100644 (file)
@@ -14,6 +14,10 @@ Supported chips:
     Prefix: 'f71882fg'
     Addresses scanned: none, address read from Super I/O config space
     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
     Prefix: 'f8000'
     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
 motherboard, so the driver assumes that the BIOS set the method
 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
 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
index 659315d98e00834bf8fb177311f0ebe041dd2b27..f9ba96c0ac4acf19573ca552703bd7014b350488 100644 (file)
@@ -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 IT8716F and late IT8712F have 6. They are shared with other functions
 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
 is stored in the Super-I/O configuration space. Due to technical limitations,
diff --git a/Documentation/hwmon/mc13783-adc b/Documentation/hwmon/mc13783-adc
new file mode 100644 (file)
index 0000000..044531a
--- /dev/null
@@ -0,0 +1,50 @@
+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
index 82def883361b1a1d30ca2e5af6f1e0a5b56c9b27..3de6b0bcb1474ecda75e9aa4ff275d3b3af67a6f 100644 (file)
@@ -225,8 +225,6 @@ pwm[1-*]_auto_point[1-*]_temp_hyst
                to PWM output channels.
                RW
 
-OR
-
 temp[1-*]_auto_point[1-*]_pwm
 temp[1-*]_auto_point[1-*]_temp
 temp[1-*]_auto_point[1-*]_temp_hyst
@@ -235,6 +233,15 @@ temp[1-*]_auto_point[1-*]_temp_hyst
                to temperature channels.
                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 *
index 6ee36dbafd64afaee72a4c308ad20c39bb5d5f15..44dd2bcc72bdd4d5fd8ab4efbf524f3b1e622706 100644 (file)
@@ -32,8 +32,6 @@ Authors:
 Module Parameters
 -----------------
 
-* force_addr: int
-  Initialize the ISA address of the sensors
 * force_i2c: int
   Initialize the I2C address of the sensors
 * init: int
@@ -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.
 
 [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.
index 107a5a5a0174d5209f92b05effaaadaba1c96bf4..746b706206da70d40f62a6998f387cdfdf182a2f 100644 (file)
@@ -327,6 +327,13 @@ M: Colin Leroy <colin@colino.net>
 S:     Maintained
 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
 M:     Matthew Wilcox <matthew@wil.cx>
 L:     linux-scsi@vger.kernel.org
@@ -2416,7 +2423,9 @@ HARDWARE MONITORING
 L:     lm-sensors@lm-sensors.org
 W:     http://www.lm-sensors.org/
 S:     Orphan
+F:     Documentation/hwmon/
 F:     drivers/hwmon/
+F:     include/linux/hwmon*.h
 
 HARDWARE RANDOM NUMBER GENERATOR CORE
 M:     Matt Mackall <mpm@selenic.com>
@@ -3312,6 +3321,12 @@ S:       Maintained
 F:     Documentation/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
 M:     Jean Delvare <khali@linux-fr.org>
 L:     lm-sensors@lm-sensors.org
index 700e93adeb3308a37fbd1e35ae948d1391f980c8..9e640c62ebd9d267c1efcc2800ae07c36854caf8 100644 (file)
@@ -191,21 +191,27 @@ config SENSORS_ADT7470
          will be called adt7470.
 
 config SENSORS_ADT7473
-       tristate "Analog Devices ADT7473"
+       tristate "Analog Devices ADT7473 (DEPRECATED)"
        depends on I2C && EXPERIMENTAL
+       select SENSORS_ADT7475
        help
          If you say yes here you get support for the Analog Devices
          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
          will be called adt7473.
 
 config SENSORS_ADT7475
-       tristate "Analog Devices ADT7475"
+       tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490"
        depends on I2C && EXPERIMENTAL
+       select HWMON_VID
        help
          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
          will be called adt7475.
@@ -305,12 +311,12 @@ config SENSORS_F71805F
          will be called f71805f.
 
 config SENSORS_F71882FG
-       tristate "Fintek F71858FG, F71862FG, F71882FG and F8000"
+       tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000"
        depends on EXPERIMENTAL
        help
          If you say yes here you get support for hardware monitoring
-         features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG
-         and F8000 Super-I/O chips.
+         features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG,
+         F71889FG and F8000 Super-I/O chips.
 
          This driver can also be built as a module.  If so, the module
          will be called f71882fg.
@@ -442,6 +448,15 @@ config SENSORS_LM70
          This driver can also be built as a module.  If so, the module
          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
        tristate "National Semiconductor LM75 and compatibles"
        depends on I2C
@@ -841,7 +856,7 @@ config SENSORS_W83781D
 
 config SENSORS_W83791D
        tristate "Winbond W83791D"
-       depends on I2C && EXPERIMENTAL
+       depends on I2C
        select HWMON_VID
        help
          If you say yes here you get support for the Winbond W83791D chip.
@@ -1008,6 +1023,12 @@ config SENSORS_APPLESMC
          Say Y here if you have an applicable laptop and want to experience
          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
 
 comment "ACPI drivers"
index 9f46cb019cc6d99e28dbec508c2d73a68a6eb384..33c2ee105284124ee1247823fc391c4611577771 100644 (file)
@@ -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_LM63)     += lm63.o
 obj-$(CONFIG_SENSORS_LM70)     += lm70.o
+obj-$(CONFIG_SENSORS_LM73)     += lm73.o
 obj-$(CONFIG_SENSORS_LM75)     += lm75.o
 obj-$(CONFIG_SENSORS_LM77)     += lm77.o
 obj-$(CONFIG_SENSORS_LM78)     += lm78.o
@@ -73,6 +74,7 @@ obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o
 obj-$(CONFIG_SENSORS_MAX1111)  += max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)  += max1619.o
 obj-$(CONFIG_SENSORS_MAX6650)  += max6650.o
+obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
 obj-$(CONFIG_SENSORS_PC87360)  += pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)  += pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)  += pcf8591.o
index afc5943181251404ddd84893f04ef49b8aab3434..33acf29531afa30598e684ed82f2a56295d8a835 100644 (file)
@@ -288,9 +288,8 @@ static int adm1021_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
-       int i;
-       const char *type_name = "";
-       int conv_rate, status, config;
+       const char *type_name;
+       int conv_rate, status, config, man_id, dev_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                pr_debug("adm1021: detect failed, "
@@ -303,62 +302,37 @@ static int adm1021_detect(struct i2c_client *client, int kind,
                                             ADM1021_REG_CONV_RATE_R);
        config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R);
 
-       /* Now, we do the remaining detection. */
-       if (kind < 0) {
-               if ((status & 0x03) != 0x00 || (config & 0x3F) != 0x00
-                   || (conv_rate & 0xF8) != 0x00) {
-                       pr_debug("adm1021: detect failed, "
-                                "chip not detected!\n");
-                       return -ENODEV;
-               }
+       /* Check unused bits */
+       if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) {
+               pr_debug("adm1021: detect failed, chip not detected!\n");
+               return -ENODEV;
        }
 
        /* Determine the chip type. */
-       if (kind <= 0) {
-               i = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_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;
-       }
+       man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID);
+       dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID);
 
-       if (kind == max1617) {
-               type_name = "max1617";
-       } else if (kind == max1617a) {
+       if (man_id == 0x4d && dev_id == 0x01)
                type_name = "max1617a";
-       } else if (kind == adm1021) {
-               type_name = "adm1021";
-       } else if (kind == adm1023) {
-               type_name = "adm1023";
-       } else if (kind == thmc10) {
+       else if (man_id == 0x41) {
+               if ((dev_id & 0xF0) == 0x30)
+                       type_name = "adm1023";
+               else
+                       type_name = "adm1021";
+       } else if (man_id == 0x49)
                type_name = "thmc10";
-       } else if (kind == lm84) {
-               type_name = "lm84";
-       } else if (kind == gl523sm) {
+       else if (man_id == 0x23)
                type_name = "gl523sm";
-       } else if (kind == mc1066) {
+       else if (man_id == 0x54)
                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",
                 type_name, i2c_adapter_id(adapter), client->addr);
        strlcpy(info->type, type_name, I2C_NAME_SIZE);
index 4db04d603ec9c7feed84b7fdeba670c480310fad..db6ac2b04f6f867ba2803b279539059faf4735db 100644 (file)
@@ -2,7 +2,7 @@
  * adm1025.c
  *
  * 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
  * 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,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
-       const char *name = "";
-       u8 config;
+       const char *name;
+       u8 man_id, chip_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       /*
-        * 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. 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.
-        */
-       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;
-               }
+       /* Check for unused bits */
+       if ((i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG) & 0x80)
+        || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0xC0)
+        || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0xBC)) {
+               dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x\n",
+                       client->addr);
+               return -ENODEV;
        }
 
-       if (kind <= 0) { /* identification */
-               u8 man_id, chip_id;
-
-               man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID);
-               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;
-               }
-       }
+       /* Identification */
+       chip_id = i2c_smbus_read_byte_data(client, ADM1025_REG_CHIP_ID);
+       if ((chip_id & 0xF0) != 0x20)
+               return -ENODEV;
 
-       if (kind == adm1025) {
+       man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID);
+       if (man_id == 0x41)
                name = "adm1025";
-       } else if (kind == ne1619) {
+       else if (man_id == 0xA1 && client->addr != 0x2E)
                name = "ne1619";
-       }
+       else
+               return -ENODEV;
+
        strlcpy(info->type, name, I2C_NAME_SIZE);
 
        return 0;
index ff7de40b6e35267c2836b03a98d4017e74e6414e..fb5363985e212d73bbef2132f6ce18e324855709 100644 (file)
@@ -1672,35 +1672,26 @@ static int adm1026_detect(struct i2c_client *client, int kind,
                i2c_adapter_id(client->adapter), client->addr,
                company, verstep);
 
-       /* If auto-detecting, Determine the chip type. */
-       if (kind <= 0) {
-               dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x "
-                       "...\n", i2c_adapter_id(adapter), address);
-               if (company == ADM1026_COMPANY_ANALOG_DEV
-                   && verstep == ADM1026_VERSTEP_ADM1026) {
-                       kind = adm1026;
-               } else if (company == ADM1026_COMPANY_ANALOG_DEV
-                       && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
-                       dev_err(&adapter->dev, "Unrecognized stepping "
-                               "0x%02x. Defaulting to ADM1026.\n", verstep);
-                       kind = adm1026;
-               } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
-                       dev_err(&adapter->dev, "Found version/stepping "
-                               "0x%02x. Assuming generic ADM1026.\n",
-                               verstep);
-                       kind = any_chip;
-               } else {
-                       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;
-               }
+       /* Determine the chip type. */
+       dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n",
+               i2c_adapter_id(adapter), address);
+       if (company == ADM1026_COMPANY_ANALOG_DEV
+           && verstep == ADM1026_VERSTEP_ADM1026) {
+               /* Analog Devices ADM1026 */
+       } else if (company == ADM1026_COMPANY_ANALOG_DEV
+               && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
+               dev_err(&adapter->dev, "Unrecognized stepping "
+                       "0x%02x. Defaulting to ADM1026.\n", verstep);
+       } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) {
+               dev_err(&adapter->dev, "Found version/stepping "
+                       "0x%02x. Assuming generic ADM1026.\n",
+                       verstep);
+       } else {
+               dev_dbg(&adapter->dev, "Autodetection failed\n");
+               /* Not an ADM1026... */
+               return -ENODEV;
        }
+
        strlcpy(info->type, "adm1026", I2C_NAME_SIZE);
 
        return 0;
index e845b75ccee4f0553f55ca322372c252020c90ab..ef91e2a4a5673b9045c636a24adda1ae0734d187 100644 (file)
@@ -301,59 +301,36 @@ static int adm1029_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        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))
                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
         * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED,
         * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values
         * documented
         */
 
-       if (kind <= 0) {        /* identification */
-               u8 man_id, chip_id, temp_devices_installed, nb_fan_support;
-
-               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,
+       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);
-               nb_fan_support = i2c_smbus_read_byte_data(client,
+       nb_fan_support = i2c_smbus_read_byte_data(client,
                                                ADM1029_REG_NB_FAN_SUPPORT);
-               /* 0x41 is Analog Devices */
-               if (man_id == 0x41 && (temp_devices_installed & 0xf9) == 0x01
-                   && nb_fan_support == 0x03) {
-                       if ((chip_id & 0xF0) == 0x00) {
-                               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);
-                       }
-               }
+       /* 0x41 is Analog Devices */
+       if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01
+           || nb_fan_support != 0x03)
+               return -ENODEV;
 
-               if (kind <= 0) {        /* identification failed */
-                       pr_debug("adm1029: Unsupported chip (man_id=0x%02X, "
-                                "chip_id=0x%02X)\n", man_id, chip_id);
-                       return -ENODEV;
-               }
+       if ((chip_id & 0xF0) != 0x00) {
+               /* There are no "official" CHIP ID, so actually
+                * we use Major/Minor revision for that */
+               pr_info("adm1029: Unknown major revision %x, "
+                       "please let us know\n", chip_id);
+               return -ENODEV;
        }
+
        strlcpy(info->type, "adm1029", I2C_NAME_SIZE);
 
        return 0;
index 56905955352cac894b0c381bad597050be236438..0e722175aae0640f8b1922caa56d33c972c8b232 100644 (file)
@@ -817,31 +817,19 @@ static int adm1031_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        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))
                return -ENODEV;
 
-       if (kind < 0) {
-               int id, co;
-               id = i2c_smbus_read_byte_data(client, 0x3d);
-               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))
-                       return -ENODEV;
-               kind = (id == 0x30) ? adm1030 : adm1031;
-       }
-
-       if (kind <= 0)
-               kind = adm1031;
+       if (!((id == 0x31 || id == 0x30) && co == 0x41))
+               return -ENODEV;
+       name = (id == 0x30) ? "adm1030" : "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);
 
        return 0;
index 2444b15f2e9d1ec87fcd8958122be6819ae07cca..20e0481cc20611aca78cc4fa5f49f68bebcea16e 100644 (file)
@@ -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))
                return -ENODEV;
 
-       if (kind == 0) {
-               kind = adm9240;
-       }
-
-       if (kind < 0) {
-
-               /* 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);
+       /* 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;
        }
 
-       /* either forced or detected chip kind */
-       if (kind == adm9240) {
+       /* check known chip manufacturer */
+       man_id = i2c_smbus_read_byte_data(new_client, ADM9240_REG_MAN_ID);
+       if (man_id == 0x23) {
                name = "adm9240";
-       } else if (kind == ds1780) {
+       } else if (man_id == 0xda) {
                name = "ds1780";
-       } else if (kind == lm81) {
+       } else if (man_id == 0x01) {
                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);
 
        return 0;
index 5c39b4af1b236723c96e9f4fd7ec19d6834d280d..451977bca7d6e02767f887951c58e8dd5c3b5cdf 100644 (file)
@@ -191,6 +191,7 @@ static int ads7828_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int ch;
 
        /* Check we have a valid client */
        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,
        - Read from the 8 channel addresses
        - Check the top 4 bits of each result are not set (12 data bits)
        */
-       if (kind < 0) {
-               int ch;
-               for (ch = 0; ch < ADS7828_NCH; ch++) {
-                       u16 in_data;
-                       u8 cmd = channel_cmd_byte(ch);
-                       in_data = ads7828_read_value(client, cmd);
-                       if (in_data & 0xF000) {
-                               printk(KERN_DEBUG
-                               "%s : Doesn't look like an ads7828 device\n",
-                               __func__);
-                               return -ENODEV;
-                       }
+       for (ch = 0; ch < ADS7828_NCH; ch++) {
+               u16 in_data;
+               u8 cmd = channel_cmd_byte(ch);
+               in_data = ads7828_read_value(client, cmd);
+               if (in_data & 0xF000) {
+                       pr_debug("%s : Doesn't look like an ads7828 device\n",
+                                __func__);
+                       return -ENODEV;
                }
        }
+
        strlcpy(info->type, "ads7828", I2C_NAME_SIZE);
 
        return 0;
index 1852f27bac51fbd9a37a6abe07fe10b50b9b7a6c..f9c9562b6a94f0e6f136528c9831922f5119b4ae 100644 (file)
@@ -1906,27 +1906,22 @@ static int adt7462_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int vendor, device, revision;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if (kind <= 0) {
-               int vendor, device, revision;
-
-               vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR);
-               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);
-               if (device != ADT7462_DEVICE)
-                       return -ENODEV;
+       device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE);
+       if (device != ADT7462_DEVICE)
+               return -ENODEV;
 
-               revision = i2c_smbus_read_byte_data(client,
-                                                   ADT7462_REG_REVISION);
-               if (revision != ADT7462_REVISION)
-                       return -ENODEV;
-       } else
-               dev_dbg(&adapter->dev, "detection forced\n");
+       revision = i2c_smbus_read_byte_data(client, ADT7462_REG_REVISION);
+       if (revision != ADT7462_REVISION)
+               return -ENODEV;
 
        strlcpy(info->type, "adt7462", I2C_NAME_SIZE);
 
index 633e1a1e9d79843f1d8feebbb276e737903b685f..32b1750a6890bb41e95bca0df47027637a3e6d65 100644 (file)
@@ -1229,27 +1229,22 @@ static int adt7470_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int vendor, device, revision;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if (kind <= 0) {
-               int vendor, device, revision;
-
-               vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR);
-               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);
-               if (device != ADT7470_DEVICE)
-                       return -ENODEV;
+       device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE);
+       if (device != ADT7470_DEVICE)
+               return -ENODEV;
 
-               revision = i2c_smbus_read_byte_data(client,
-                                                   ADT7470_REG_REVISION);
-               if (revision != ADT7470_REVISION)
-                       return -ENODEV;
-       } else
-               dev_dbg(&adapter->dev, "detection forced\n");
+       revision = i2c_smbus_read_byte_data(client, ADT7470_REG_REVISION);
+       if (revision != ADT7470_REVISION)
+               return -ENODEV;
 
        strlcpy(info->type, "adt7470", I2C_NAME_SIZE);
 
index 0a6ce2367b42ae62bf2644a30bd2b5a739be2df4..aea244db974e1acfdf63a552f649ddc1fea063b9 100644 (file)
@@ -174,7 +174,6 @@ static const struct i2c_device_id adt7473_id[] = {
        { "adt7473", adt7473 },
        { }
 };
-MODULE_DEVICE_TABLE(i2c, adt7473_id);
 
 static struct i2c_driver adt7473_driver = {
        .class          = I2C_CLASS_HWMON,
@@ -1090,27 +1089,22 @@ static int adt7473_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int vendor, device, revision;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if (kind <= 0) {
-               int vendor, device, revision;
-
-               vendor = i2c_smbus_read_byte_data(client, ADT7473_REG_VENDOR);
-               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);
-               if (device != ADT7473_DEVICE)
-                       return -ENODEV;
+       device = i2c_smbus_read_byte_data(client, ADT7473_REG_DEVICE);
+       if (device != ADT7473_DEVICE)
+               return -ENODEV;
 
-               revision = i2c_smbus_read_byte_data(client,
-                                                   ADT7473_REG_REVISION);
-               if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
-                       return -ENODEV;
-       } else
-               dev_dbg(&adapter->dev, "detection forced\n");
+       revision = i2c_smbus_read_byte_data(client, ADT7473_REG_REVISION);
+       if (revision != ADT7473_REV_68 && revision != ADT7473_REV_69)
+               return -ENODEV;
 
        strlcpy(info->type, "adt7473", I2C_NAME_SIZE);
 
@@ -1171,6 +1165,8 @@ static int adt7473_remove(struct i2c_client *client)
 
 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);
 }
 
index b5a95193c694a44f5c142cd9e5d1fd52c10b93b6..99abfddedbc3b842be2c017c0eb2e071693917e5 100644 (file)
@@ -3,7 +3,8 @@
  * Copyright (C) 2007-2008, Advanced Micro Devices, Inc.
  * Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
  * Copyright (C) 2008 Hans de Goede <hdegoede@redhat.com>
-
+ * Copyright (C) 2009 Jean Delvare <khali@linux-fr.org>
+ *
  * Derived from the lm83 driver by Jean Delvare
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,6 +18,7 @@
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
 #include <linux/err.h>
 
 /* Indexes for the sysfs hooks */
 
 /* 7475 Common Registers */
 
-#define REG_VOLTAGE_BASE       0x21
+#define REG_DEVREV2            0x12    /* ADT7490 only */
+
+#define REG_VTT                        0x1E    /* ADT7490 only */
+#define REG_EXTEND3            0x1F    /* ADT7490 only */
+
+#define REG_VOLTAGE_BASE       0x20
 #define REG_TEMP_BASE          0x25
 #define REG_TACH_BASE          0x28
 #define REG_PWM_BASE           0x30
 
 #define REG_DEVID              0x3D
 #define REG_VENDID             0x3E
+#define REG_DEVID2             0x3F
 
 #define REG_STATUS1            0x41
 #define REG_STATUS2            0x42
 
-#define REG_VOLTAGE_MIN_BASE   0x46
-#define REG_VOLTAGE_MAX_BASE   0x47
+#define REG_VID                        0x43    /* ADT7476 only */
+
+#define REG_VOLTAGE_MIN_BASE   0x44
+#define REG_VOLTAGE_MAX_BASE   0x45
 
 #define REG_TEMP_MIN_BASE      0x4E
 #define REG_TEMP_MAX_BASE      0x4F
 
 #define REG_TEMP_OFFSET_BASE   0x70
 
+#define REG_CONFIG2            0x73
+
 #define REG_EXTEND1            0x76
 #define REG_EXTEND2            0x77
+
+#define REG_CONFIG3            0x78
 #define REG_CONFIG5            0x7C
+#define REG_CONFIG4            0x7D
+
+#define REG_STATUS4            0x81    /* ADT7490 only */
+
+#define REG_VTT_MIN            0x84    /* ADT7490 only */
+#define REG_VTT_MAX            0x86    /* ADT7490 only */
+
+#define VID_VIDSEL             0x80    /* ADT7476 only */
+
+#define CONFIG2_ATTN           0x20
+
+#define CONFIG3_SMBALERT       0x01
+#define CONFIG3_THERM          0x02
+
+#define CONFIG4_PINFUNC                0x03
+#define CONFIG4_MAXDUTY                0x08
+#define CONFIG4_ATTN_IN10      0x30
+#define CONFIG4_ATTN_IN43      0xC0
 
 #define CONFIG5_TWOSCOMP       0x01
 #define CONFIG5_TEMPOFFSET     0x02
+#define CONFIG5_VIDGPIO                0x10    /* ADT7476 only */
 
 /* ADT7475 Settings */
 
-#define ADT7475_VOLTAGE_COUNT  2
+#define ADT7475_VOLTAGE_COUNT  5       /* Not counting Vtt */
 #define ADT7475_TEMP_COUNT     3
 #define ADT7475_TACH_COUNT     4
 #define ADT7475_PWM_COUNT      3
 #define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx))
 #define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx))
 
-static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
 
-I2C_CLIENT_INSMOD_1(adt7475);
+I2C_CLIENT_INSMOD_4(adt7473, adt7475, adt7476, adt7490);
 
 static const struct i2c_device_id adt7475_id[] = {
+       { "adt7473", adt7473 },
        { "adt7475", adt7475 },
+       { "adt7476", adt7476 },
+       { "adt7490", adt7490 },
        { }
 };
 MODULE_DEVICE_TABLE(i2c, adt7475_id);
@@ -131,15 +167,24 @@ struct adt7475_data {
        unsigned long limits_updated;
        char valid;
 
+       u8 config4;
        u8 config5;
-       u16 alarms;
-       u16 voltage[3][3];
+       u8 has_voltage;
+       u8 bypass_attn;         /* Bypass voltage attenuator */
+       u8 has_pwm2:1;
+       u8 has_fan4:1;
+       u8 has_vid:1;
+       u32 alarms;
+       u16 voltage[3][6];
        u16 temp[7][3];
        u16 tach[2][4];
        u8 pwm[4][3];
        u8 range[3];
        u8 pwmctl[3];
        u8 pwmchan[3];
+
+       u8 vid;
+       u8 vrm;
 };
 
 static struct i2c_driver adt7475_driver;
@@ -196,26 +241,35 @@ static inline u16 rpm2tach(unsigned long rpm)
        return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF);
 }
 
-static inline int reg2vcc(u16 reg)
-{
-       return (4296 * reg) / 1000;
-}
+/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */
+static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = {
+       { 45, 94 },     /* +2.5V */
+       { 175, 525 },   /* Vccp */
+       { 68, 71 },     /* Vcc */
+       { 93, 47 },     /* +5V */
+       { 120, 20 },    /* +12V */
+       { 45, 45 },     /* Vtt */
+};
 
-static inline int reg2vccp(u16 reg)
+static inline int reg2volt(int channel, u16 reg, u8 bypass_attn)
 {
-       return (2929 * reg) / 1000;
-}
+       const int *r = adt7473_in_scaling[channel];
 
-static inline u16 vcc2reg(long vcc)
-{
-       vcc = SENSORS_LIMIT(vcc, 0, 4396);
-       return (vcc * 1000) / 4296;
+       if (bypass_attn & (1 << channel))
+               return DIV_ROUND_CLOSEST(reg * 2250, 1024);
+       return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024);
 }
 
-static inline u16 vccp2reg(long vcc)
+static inline u16 volt2reg(int channel, long volt, u8 bypass_attn)
 {
-       vcc = SENSORS_LIMIT(vcc, 0, 2998);
-       return (vcc * 1000) / 2929;
+       const int *r = adt7473_in_scaling[channel];
+       long reg;
+
+       if (bypass_attn & (1 << channel))
+               reg = (volt * 1024) / 2250;
+       else
+               reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250);
+       return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2);
 }
 
 static u16 adt7475_read_word(struct i2c_client *client, int reg)
@@ -271,12 +325,11 @@ static ssize_t show_voltage(struct device *dev, struct device_attribute *attr,
        switch (sattr->nr) {
        case ALARM:
                return sprintf(buf, "%d\n",
-                              (data->alarms >> (sattr->index + 1)) & 1);
+                              (data->alarms >> sattr->index) & 1);
        default:
                val = data->voltage[sattr->nr][sattr->index];
                return sprintf(buf, "%d\n",
-                              sattr->index ==
-                              0 ? reg2vccp(val) : reg2vcc(val));
+                              reg2volt(sattr->index, val, data->bypass_attn));
        }
 }
 
@@ -296,12 +349,19 @@ static ssize_t set_voltage(struct device *dev, struct device_attribute *attr,
        mutex_lock(&data->lock);
 
        data->voltage[sattr->nr][sattr->index] =
-               sattr->index ? vcc2reg(val) : vccp2reg(val);
+                               volt2reg(sattr->index, val, data->bypass_attn);
 
-       if (sattr->nr == MIN)
-               reg = VOLTAGE_MIN_REG(sattr->index);
-       else
-               reg = VOLTAGE_MAX_REG(sattr->index);
+       if (sattr->index < ADT7475_VOLTAGE_COUNT) {
+               if (sattr->nr == MIN)
+                       reg = VOLTAGE_MIN_REG(sattr->index);
+               else
+                       reg = VOLTAGE_MAX_REG(sattr->index);
+       } else {
+               if (sattr->nr == MIN)
+                       reg = REG_VTT_MIN;
+               else
+                       reg = REG_VTT_MAX;
+       }
 
        i2c_smbus_write_byte_data(client, reg,
                                  data->voltage[sattr->nr][sattr->index] >> 2);
@@ -778,18 +838,103 @@ static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 0);
-static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage,
+static ssize_t show_pwm_at_crit(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       struct adt7475_data *data = adt7475_update_device(dev);
+       return sprintf(buf, "%d\n", !!(data->config4 & CONFIG4_MAXDUTY));
+}
+
+static ssize_t set_pwm_at_crit(struct device *dev,
+                              struct device_attribute *devattr,
+                              const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct adt7475_data *data = i2c_get_clientdata(client);
+       long val;
+
+       if (strict_strtol(buf, 10, &val))
+               return -EINVAL;
+       if (val != 0 && val != 1)
+               return -EINVAL;
+
+       mutex_lock(&data->lock);
+       data->config4 = i2c_smbus_read_byte_data(client, REG_CONFIG4);
+       if (val)
+               data->config4 |= CONFIG4_MAXDUTY;
+       else
+               data->config4 &= ~CONFIG4_MAXDUTY;
+       i2c_smbus_write_byte_data(client, REG_CONFIG4, data->config4);
+       mutex_unlock(&data->lock);
+
+       return count;
+}
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *devattr,
+                       char *buf)
+{
+       struct adt7475_data *data = dev_get_drvdata(dev);
+       return sprintf(buf, "%d\n", (int)data->vrm);
+}
+
+static ssize_t set_vrm(struct device *dev, struct device_attribute *devattr,
+                      const char *buf, size_t count)
+{
+       struct adt7475_data *data = dev_get_drvdata(dev);
+       long val;
+
+       if (strict_strtol(buf, 10, &val))
+               return -EINVAL;
+       if (val < 0 || val > 255)
+               return -EINVAL;
+       data->vrm = val;
+
+       return count;
+}
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *devattr,
+                       char *buf)
+{
+       struct adt7475_data *data = adt7475_update_device(dev);
+       return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_voltage, NULL, INPUT, 0);
+static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_voltage,
                            set_voltage, MAX, 0);
-static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage,
+static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_voltage,
                            set_voltage, MIN, 0);
-static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0);
-static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 1);
-static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage,
+static SENSOR_DEVICE_ATTR_2(in0_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0);
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 1);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage,
                            set_voltage, MAX, 1);
-static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage,
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage,
                            set_voltage, MIN, 1);
-static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1);
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 2);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MAX, 2);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MIN, 2);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 2);
+static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_voltage, NULL, INPUT, 3);
+static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MAX, 3);
+static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MIN, 3);
+static SENSOR_DEVICE_ATTR_2(in3_alarm, S_IRUGO, show_voltage, NULL, ALARM, 3);
+static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_voltage, NULL, INPUT, 4);
+static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MAX, 4);
+static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MIN, 4);
+static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, show_voltage, NULL, ALARM, 8);
+static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_voltage, NULL, INPUT, 5);
+static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MAX, 5);
+static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_voltage,
+                           set_voltage, MIN, 5);
+static SENSOR_DEVICE_ATTR_2(in5_alarm, S_IRUGO, show_voltage, NULL, ALARM, 31);
 static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0);
 static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0);
 static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0);
@@ -893,6 +1038,13 @@ static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm,
 static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm,
                            set_pwm, MAX, 2);
 
+/* Non-standard name, might need revisiting */
+static DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO,
+                  show_pwm_at_crit, set_pwm_at_crit);
+
+static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, set_vrm);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
 static struct attribute *adt7475_attrs[] = {
        &sensor_dev_attr_in1_input.dev_attr.attr,
        &sensor_dev_attr_in1_max.dev_attr.attr,
@@ -940,60 +1092,156 @@ static struct attribute *adt7475_attrs[] = {
        &sensor_dev_attr_fan3_input.dev_attr.attr,
        &sensor_dev_attr_fan3_min.dev_attr.attr,
        &sensor_dev_attr_fan3_alarm.dev_attr.attr,
-       &sensor_dev_attr_fan4_input.dev_attr.attr,
-       &sensor_dev_attr_fan4_min.dev_attr.attr,
-       &sensor_dev_attr_fan4_alarm.dev_attr.attr,
        &sensor_dev_attr_pwm1.dev_attr.attr,
        &sensor_dev_attr_pwm1_freq.dev_attr.attr,
        &sensor_dev_attr_pwm1_enable.dev_attr.attr,
        &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr,
        &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr,
        &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr,
-       &sensor_dev_attr_pwm2.dev_attr.attr,
-       &sensor_dev_attr_pwm2_freq.dev_attr.attr,
-       &sensor_dev_attr_pwm2_enable.dev_attr.attr,
-       &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
-       &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
-       &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
        &sensor_dev_attr_pwm3.dev_attr.attr,
        &sensor_dev_attr_pwm3_freq.dev_attr.attr,
        &sensor_dev_attr_pwm3_enable.dev_attr.attr,
        &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr,
        &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr,
        &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr,
+       &dev_attr_pwm_use_point2_pwm_at_crit.attr,
        NULL,
 };
 
-struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
+static struct attribute *fan4_attrs[] = {
+       &sensor_dev_attr_fan4_input.dev_attr.attr,
+       &sensor_dev_attr_fan4_min.dev_attr.attr,
+       &sensor_dev_attr_fan4_alarm.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *pwm2_attrs[] = {
+       &sensor_dev_attr_pwm2.dev_attr.attr,
+       &sensor_dev_attr_pwm2_freq.dev_attr.attr,
+       &sensor_dev_attr_pwm2_enable.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr,
+       &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *in0_attrs[] = {
+       &sensor_dev_attr_in0_input.dev_attr.attr,
+       &sensor_dev_attr_in0_max.dev_attr.attr,
+       &sensor_dev_attr_in0_min.dev_attr.attr,
+       &sensor_dev_attr_in0_alarm.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *in3_attrs[] = {
+       &sensor_dev_attr_in3_input.dev_attr.attr,
+       &sensor_dev_attr_in3_max.dev_attr.attr,
+       &sensor_dev_attr_in3_min.dev_attr.attr,
+       &sensor_dev_attr_in3_alarm.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *in4_attrs[] = {
+       &sensor_dev_attr_in4_input.dev_attr.attr,
+       &sensor_dev_attr_in4_max.dev_attr.attr,
+       &sensor_dev_attr_in4_min.dev_attr.attr,
+       &sensor_dev_attr_in4_alarm.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *in5_attrs[] = {
+       &sensor_dev_attr_in5_input.dev_attr.attr,
+       &sensor_dev_attr_in5_max.dev_attr.attr,
+       &sensor_dev_attr_in5_min.dev_attr.attr,
+       &sensor_dev_attr_in5_alarm.dev_attr.attr,
+       NULL
+};
+
+static struct attribute *vid_attrs[] = {
+       &dev_attr_cpu0_vid.attr,
+       &dev_attr_vrm.attr,
+       NULL
+};
+
+static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs };
+static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs };
+static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs };
+static struct attribute_group in0_attr_group = { .attrs = in0_attrs };
+static struct attribute_group in3_attr_group = { .attrs = in3_attrs };
+static struct attribute_group in4_attr_group = { .attrs = in4_attrs };
+static struct attribute_group in5_attr_group = { .attrs = in5_attrs };
+static struct attribute_group vid_attr_group = { .attrs = vid_attrs };
 
 static int adt7475_detect(struct i2c_client *client, int kind,
                          struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int vendid, devid, devid2;
+       const char *name;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if (kind <= 0) {
-               if (adt7475_read(REG_VENDID) != 0x41 ||
-                   adt7475_read(REG_DEVID) != 0x75) {
-                       dev_err(&adapter->dev,
-                               "Couldn't detect a adt7475 part at 0x%02x\n",
-                               (unsigned int)client->addr);
-                       return -ENODEV;
-               }
+       vendid = adt7475_read(REG_VENDID);
+       devid2 = adt7475_read(REG_DEVID2);
+       if (vendid != 0x41 ||           /* Analog Devices */
+           (devid2 & 0xf8) != 0x68)
+               return -ENODEV;
+
+       devid = adt7475_read(REG_DEVID);
+       if (devid == 0x73)
+               name = "adt7473";
+       else if (devid == 0x75 && client->addr == 0x2e)
+               name = "adt7475";
+       else if (devid == 0x76)
+               name = "adt7476";
+       else if ((devid2 & 0xfc) == 0x6c)
+               name = "adt7490";
+       else {
+               dev_dbg(&adapter->dev,
+                       "Couldn't detect an ADT7473/75/76/90 part at "
+                       "0x%02x\n", (unsigned int)client->addr);
+               return -ENODEV;
        }
 
-       strlcpy(info->type, adt7475_id[0].name, I2C_NAME_SIZE);
+       strlcpy(info->type, name, I2C_NAME_SIZE);
 
        return 0;
 }
 
+static void adt7475_remove_files(struct i2c_client *client,
+                                struct adt7475_data *data)
+{
+       sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+       if (data->has_fan4)
+               sysfs_remove_group(&client->dev.kobj, &fan4_attr_group);
+       if (data->has_pwm2)
+               sysfs_remove_group(&client->dev.kobj, &pwm2_attr_group);
+       if (data->has_voltage & (1 << 0))
+               sysfs_remove_group(&client->dev.kobj, &in0_attr_group);
+       if (data->has_voltage & (1 << 3))
+               sysfs_remove_group(&client->dev.kobj, &in3_attr_group);
+       if (data->has_voltage & (1 << 4))
+               sysfs_remove_group(&client->dev.kobj, &in4_attr_group);
+       if (data->has_voltage & (1 << 5))
+               sysfs_remove_group(&client->dev.kobj, &in5_attr_group);
+       if (data->has_vid)
+               sysfs_remove_group(&client->dev.kobj, &vid_attr_group);
+}
+
 static int adt7475_probe(struct i2c_client *client,
                         const struct i2c_device_id *id)
 {
+       static const char *names[] = {
+               [adt7473] = "ADT7473",
+               [adt7475] = "ADT7475",
+               [adt7476] = "ADT7476",
+               [adt7490] = "ADT7490",
+       };
+
        struct adt7475_data *data;
-       int i, ret = 0;
+       int i, ret = 0, revision;
+       u8 config2, config3;
 
        data = kzalloc(sizeof(*data), GFP_KERNEL);
        if (data == NULL)
@@ -1002,6 +1250,70 @@ static int adt7475_probe(struct i2c_client *client,
        mutex_init(&data->lock);
        i2c_set_clientdata(client, data);
 
+       /* Initialize device-specific values */
+       switch (id->driver_data) {
+       case adt7476:
+               data->has_voltage = 0x0e;       /* in1 to in3 */
+               revision = adt7475_read(REG_DEVID2) & 0x07;
+               break;
+       case adt7490:
+               data->has_voltage = 0x3e;       /* in1 to in5 */
+               revision = adt7475_read(REG_DEVID2) & 0x03;
+               if (revision == 0x03)
+                       revision += adt7475_read(REG_DEVREV2);
+               break;
+       default:
+               data->has_voltage = 0x06;       /* in1, in2 */
+               revision = adt7475_read(REG_DEVID2) & 0x07;
+       }
+
+       config3 = adt7475_read(REG_CONFIG3);
+       /* Pin PWM2 may alternatively be used for ALERT output */
+       if (!(config3 & CONFIG3_SMBALERT))
+               data->has_pwm2 = 1;
+       /* Meaning of this bit is inverted for the ADT7473-1 */
+       if (id->driver_data == adt7473 && revision >= 1)
+               data->has_pwm2 = !data->has_pwm2;
+
+       data->config4 = adt7475_read(REG_CONFIG4);
+       /* Pin TACH4 may alternatively be used for THERM */
+       if ((data->config4 & CONFIG4_PINFUNC) == 0x0)
+               data->has_fan4 = 1;
+
+       /* THERM configuration is more complex on the ADT7476 and ADT7490,
+          because 2 different pins (TACH4 and +2.5 Vin) can be used for
+          this function */
+       if (id->driver_data == adt7490) {
+               if ((data->config4 & CONFIG4_PINFUNC) == 0x1 &&
+                   !(config3 & CONFIG3_THERM))
+                       data->has_fan4 = 1;
+       }
+       if (id->driver_data == adt7476 || id->driver_data == adt7490) {
+               if (!(config3 & CONFIG3_THERM) ||
+                   (data->config4 & CONFIG4_PINFUNC) == 0x1)
+                       data->has_voltage |= (1 << 0);          /* in0 */
+       }
+
+       /* On the ADT7476, the +12V input pin may instead be used as VID5,
+          and VID pins may alternatively be used as GPIO */
+       if (id->driver_data == adt7476) {
+               u8 vid = adt7475_read(REG_VID);
+               if (!(vid & VID_VIDSEL))
+                       data->has_voltage |= (1 << 4);          /* in4 */
+
+               data->has_vid = !(adt7475_read(REG_CONFIG5) & CONFIG5_VIDGPIO);
+       }
+
+       /* Voltage attenuators can be bypassed, globally or individually */
+       config2 = adt7475_read(REG_CONFIG2);
+       if (config2 & CONFIG2_ATTN) {
+               data->bypass_attn = (0x3 << 3) | 0x3;
+       } else {
+               data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) |
+                                   ((data->config4 & CONFIG4_ATTN_IN43) >> 3);
+       }
+       data->bypass_attn &= data->has_voltage;
+
        /* Call adt7475_read_pwm for all pwm's as this will reprogram any
           pwm's which are disabled to manual mode with 0% duty cycle */
        for (i = 0; i < ADT7475_PWM_COUNT; i++)
@@ -1011,16 +1323,70 @@ static int adt7475_probe(struct i2c_client *client,
        if (ret)
                goto efree;
 
+       /* Features that can be disabled individually */
+       if (data->has_fan4) {
+               ret = sysfs_create_group(&client->dev.kobj, &fan4_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+       if (data->has_pwm2) {
+               ret = sysfs_create_group(&client->dev.kobj, &pwm2_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+       if (data->has_voltage & (1 << 0)) {
+               ret = sysfs_create_group(&client->dev.kobj, &in0_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+       if (data->has_voltage & (1 << 3)) {
+               ret = sysfs_create_group(&client->dev.kobj, &in3_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+       if (data->has_voltage & (1 << 4)) {
+               ret = sysfs_create_group(&client->dev.kobj, &in4_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+       if (data->has_voltage & (1 << 5)) {
+               ret = sysfs_create_group(&client->dev.kobj, &in5_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+       if (data->has_vid) {
+               data->vrm = vid_which_vrm();
+               ret = sysfs_create_group(&client->dev.kobj, &vid_attr_group);
+               if (ret)
+                       goto eremove;
+       }
+
        data->hwmon_dev = hwmon_device_register(&client->dev);
        if (IS_ERR(data->hwmon_dev)) {
                ret = PTR_ERR(data->hwmon_dev);
                goto eremove;
        }
 
+       dev_info(&client->dev, "%s device, revision %d\n",
+                names[id->driver_data], revision);
+       if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2)
+               dev_info(&client->dev, "Optional features:%s%s%s%s%s\n",
+                        (data->has_voltage & (1 << 0)) ? " in0" : "",
+                        (data->has_voltage & (1 << 4)) ? " in4" : "",
+                        data->has_fan4 ? " fan4" : "",
+                        data->has_pwm2 ? " pwm2" : "",
+                        data->has_vid ? " vid" : "");
+       if (data->bypass_attn)
+               dev_info(&client->dev, "Bypassing attenuators on:%s%s%s%s\n",
+                        (data->bypass_attn & (1 << 0)) ? " in0" : "",
+                        (data->bypass_attn & (1 << 1)) ? " in1" : "",
+                        (data->bypass_attn & (1 << 3)) ? " in3" : "",
+                        (data->bypass_attn & (1 << 4)) ? " in4" : "");
+
        return 0;
 
 eremove:
-       sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+       adt7475_remove_files(client, data);
 efree:
        kfree(data);
        return ret;
@@ -1031,7 +1397,7 @@ static int adt7475_remove(struct i2c_client *client)
        struct adt7475_data *data = i2c_get_clientdata(client);
 
        hwmon_device_unregister(data->hwmon_dev);
-       sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group);
+       adt7475_remove_files(client, data);
        kfree(data);
 
        return 0;
@@ -1116,7 +1482,7 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct adt7475_data *data = i2c_get_clientdata(client);
-       u8 ext;
+       u16 ext;
        int i;
 
        mutex_lock(&data->lock);
@@ -1127,25 +1493,44 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
                data->alarms = adt7475_read(REG_STATUS2) << 8;
                data->alarms |= adt7475_read(REG_STATUS1);
 
-               ext = adt7475_read(REG_EXTEND1);
-               for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++)
+               ext = (adt7475_read(REG_EXTEND2) << 8) |
+                       adt7475_read(REG_EXTEND1);
+               for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
+                       if (!(data->has_voltage & (1 << i)))
+                               continue;
                        data->voltage[INPUT][i] =
                                (adt7475_read(VOLTAGE_REG(i)) << 2) |
-                               ((ext >> ((i + 1) * 2)) & 3);
+                               ((ext >> (i * 2)) & 3);
+               }
 
-               ext = adt7475_read(REG_EXTEND2);
                for (i = 0; i < ADT7475_TEMP_COUNT; i++)
                        data->temp[INPUT][i] =
                                (adt7475_read(TEMP_REG(i)) << 2) |
-                               ((ext >> ((i + 1) * 2)) & 3);
+                               ((ext >> ((i + 5) * 2)) & 3);
 
-               for (i = 0; i < ADT7475_TACH_COUNT; i++)
+               if (data->has_voltage & (1 << 5)) {
+                       data->alarms |= adt7475_read(REG_STATUS4) << 24;
+                       ext = adt7475_read(REG_EXTEND3);
+                       data->voltage[INPUT][5] = adt7475_read(REG_VTT) << 2 |
+                               ((ext >> 4) & 3);
+               }
+
+               for (i = 0; i < ADT7475_TACH_COUNT; i++) {
+                       if (i == 3 && !data->has_fan4)
+                               continue;
                        data->tach[INPUT][i] =
                                adt7475_read_word(client, TACH_REG(i));
+               }
 
                /* Updated by hw when in auto mode */
-               for (i = 0; i < ADT7475_PWM_COUNT; i++)
+               for (i = 0; i < ADT7475_PWM_COUNT; i++) {
+                       if (i == 1 && !data->has_pwm2)
+                               continue;
                        data->pwm[INPUT][i] = adt7475_read(PWM_REG(i));
+               }
+
+               if (data->has_vid)
+                       data->vid = adt7475_read(REG_VID) & 0x3f;
 
                data->measure_updated = jiffies;
        }
@@ -1153,9 +1538,12 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
        /* Limits and settings, should never change update every 60 seconds */
        if (time_after(jiffies, data->limits_updated + HZ * 60) ||
            !data->valid) {
+               data->config4 = adt7475_read(REG_CONFIG4);
                data->config5 = adt7475_read(REG_CONFIG5);
 
                for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) {
+                       if (!(data->has_voltage & (1 << i)))
+                               continue;
                        /* Adjust values so they match the input precision */
                        data->voltage[MIN][i] =
                                adt7475_read(VOLTAGE_MIN_REG(i)) << 2;
@@ -1163,6 +1551,11 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
                                adt7475_read(VOLTAGE_MAX_REG(i)) << 2;
                }
 
+               if (data->has_voltage & (1 << 5)) {
+                       data->voltage[MIN][5] = adt7475_read(REG_VTT_MIN) << 2;
+                       data->voltage[MAX][5] = adt7475_read(REG_VTT_MAX) << 2;
+               }
+
                for (i = 0; i < ADT7475_TEMP_COUNT; i++) {
                        /* Adjust values so they match the input precision */
                        data->temp[MIN][i] =
@@ -1178,11 +1571,16 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
                }
                adt7475_read_hystersis(client);
 
-               for (i = 0; i < ADT7475_TACH_COUNT; i++)
+               for (i = 0; i < ADT7475_TACH_COUNT; i++) {
+                       if (i == 3 && !data->has_fan4)
+                               continue;
                        data->tach[MIN][i] =
                                adt7475_read_word(client, TACH_MIN_REG(i));
+               }
 
                for (i = 0; i < ADT7475_PWM_COUNT; i++) {
+                       if (i == 1 && !data->has_pwm2)
+                               continue;
                        data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i));
                        data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i));
                        /* Set the channel and control information */
index 8acf82977e7b4b4affa8d9135b8bbe3b7ab98440..480f80ea1fa00c1082ee7d89d381c8ba84a002ae 100644 (file)
@@ -701,6 +701,7 @@ static int asb100_detect(struct i2c_client *client, int kind,
                         struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int val1, val2;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                pr_debug("asb100.o: detect failed, "
@@ -708,50 +709,30 @@ static int asb100_detect(struct i2c_client *client, int kind,
                return -ENODEV;
        }
 
-       /* The chip may be stuck in some other bank than bank 0. This may
-          make reading other information impossible. Specify a force=... or
-          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;
-               }
+       val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK);
+       val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
 
-       } /* 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
-          Winbond. Put it now into bank 0 and Vendor ID High Byte */
+       /* Put it now into bank 0 and Vendor ID High Byte */
        i2c_smbus_write_byte_data(client, ASB100_REG_BANK,
                (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78)
                | 0x80);
 
        /* Determine the chip type. */
-       if (kind <= 0) {
-               int val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID);
-               int val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
-
-               if ((val1 == 0x31) && (val2 == 0x06))
-                       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;
-               }
-       }
+       val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID);
+       val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN);
+
+       if (val1 != 0x31 || val2 != 0x06)
+               return -ENODEV;
 
        strlcpy(info->type, "asb100", I2C_NAME_SIZE);
 
index 27d62574284fa14faefbaa754f53bdc0244bcbfc..4377bb0cc5269d755e1b20095a095feedfb1e592 100644 (file)
@@ -2220,33 +2220,23 @@ static int dme1737_i2c_detect(struct i2c_client *client, int kind,
                return -ENODEV;
        }
 
-       /* A negative kind means that the driver was loaded with no force
-        * parameter (default), so we must identify the chip. */
-       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;
-               }
-       }
+       company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY);
+       verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP);
 
-       if (kind == sch5027) {
+       if (company == DME1737_COMPANY_SMSC &&
+           verstep == SCH5027_VERSTEP) {
                name = "sch5027";
-       } else {
-               kind = dme1737;
+
+       } else if (company == DME1737_COMPANY_SMSC &&
+                  (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) {
                name = "dme1737";
+       } else {
+               return -ENODEV;
        }
 
        dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n",
-                kind == sch5027 ? "SCH5027" : "DME1737", client->addr,
-                verstep);
+                verstep == SCH5027_VERSTEP ? "SCH5027" : "DME1737",
+                client->addr, verstep);
        strlcpy(info->type, name, I2C_NAME_SIZE);
 
        return 0;
index 53f88f5118167a8e3ebfb392ed199fb3f3c31175..2a4c6a05b14f594b5760f3d62c98b07d7dbc0bcc 100644 (file)
@@ -237,20 +237,16 @@ static int ds1621_detect(struct i2c_client *client, int kind,
                return -ENODEV;
 
        /* 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 during the latest 10ms, which is highly 
-                  improbable in our case. */
-               conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
-               if (conf < 0 || conf & DS1621_REG_CONFIG_NVB)
+       /* The NVB bit should be low if no EEPROM write has been  requested
+          during the latest 10ms, which is highly improbable in our case. */
+       conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF);
+       if (conf < 0 || conf & DS1621_REG_CONFIG_NVB)
+               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;
-               /* 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);
index 4146105f1a5779a5de55006444b9de99e90e8319..a95fa4256caa2af12f1b556a73837f4624d0fbcf 100644 (file)
@@ -48,6 +48,7 @@
 #define SIO_F71858_ID          0x0507  /* Chipset ID */
 #define SIO_F71862_ID          0x0601  /* Chipset ID */
 #define SIO_F71882_ID          0x0541  /* Chipset ID */
+#define SIO_F71889_ID          0x0723  /* Chipset ID */
 #define SIO_F8000_ID           0x0581  /* Chipset ID */
 
 #define REGION_LENGTH          8
@@ -95,12 +96,13 @@ static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71858fg, f71862fg, f71882fg, f8000 };
+enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 };
 
 static const char *f71882fg_names[] = {
        "f71858fg",
        "f71862fg",
        "f71882fg",
+       "f71889fg",
        "f8000",
 };
 
@@ -155,7 +157,7 @@ struct f71882fg_data {
        u8      pwm_auto_point_hyst[2];
        u8      pwm_auto_point_mapping[4];
        u8      pwm_auto_point_pwm[4][5];
-       u8      pwm_auto_point_temp[4][4];
+       s8      pwm_auto_point_temp[4][4];
 };
 
 /* Sysfs in */
@@ -258,7 +260,9 @@ static struct platform_driver f71882fg_driver = {
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-/* Temp and in attr for the f71858fg */
+/* Temp and in attr for the f71858fg, the f71858fg is special as it
+   has its temperature indexes start at 0 (the others start at 1) and
+   it only has 3 voltage inputs */
 static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = {
        SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
        SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
@@ -302,8 +306,8 @@ static struct sensor_device_attribute_2 f71858fg_in_temp_attr[] = {
        SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
 };
 
-/* Temp and in attr common to both the f71862fg and f71882fg */
-static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
+/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */
+static struct sensor_device_attribute_2 fxxxx_in_temp_attr[] = {
        SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
        SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1),
        SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2),
@@ -371,8 +375,8 @@ static struct sensor_device_attribute_2 f718x2fg_in_temp_attr[] = {
        SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
 };
 
-/* Temp and in attr found only on the f71882fg */
-static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
+/* For models with in1 alarm capability */
+static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
        SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
                0, 1),
        SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
@@ -383,6 +387,7 @@ static struct sensor_device_attribute_2 f71882fg_in_temp_attr[] = {
 /* Temp and in attr for the f8000
    Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
    is used as hysteresis value to clear alarms
+   Also like the f71858fg its temperature indexes start at 0
  */
 static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
        SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0),
@@ -413,61 +418,70 @@ static struct sensor_device_attribute_2 f8000_in_temp_attr[] = {
 };
 
 /* Fan / PWM attr common to all models */
-static struct sensor_device_attribute_2 fxxxx_fan_attr[] = {
+static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
        SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
        SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR,
                      show_fan_full_speed,
                      store_fan_full_speed, 0, 0),
        SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0),
-       SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
-       SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
-                     show_fan_full_speed,
-                     store_fan_full_speed, 0, 1),
-       SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
-       SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
-       SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
-                     show_fan_full_speed,
-                     store_fan_full_speed, 0, 2),
-       SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
-
        SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0),
        SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
                      store_pwm_enable, 0, 0),
        SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR,
                      show_pwm_interpolate, store_pwm_interpolate, 0, 0),
-       SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
-                     show_pwm_auto_point_channel,
-                     store_pwm_auto_point_channel, 0, 0),
-
+}, {
+       SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1),
+       SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR,
+                     show_fan_full_speed,
+                     store_fan_full_speed, 0, 1),
+       SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1),
        SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1),
        SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
                      store_pwm_enable, 0, 1),
        SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR,
                      show_pwm_interpolate, store_pwm_interpolate, 0, 1),
-       SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
-                     show_pwm_auto_point_channel,
-                     store_pwm_auto_point_channel, 0, 1),
-
+}, {
+       SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2),
+       SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR,
+                     show_fan_full_speed,
+                     store_fan_full_speed, 0, 2),
+       SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2),
        SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2),
        SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
                      store_pwm_enable, 0, 2),
        SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR,
                      show_pwm_interpolate, store_pwm_interpolate, 0, 2),
-       SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
-                     show_pwm_auto_point_channel,
-                     store_pwm_auto_point_channel, 0, 2),
-};
+}, {
+       SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
+       SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
+                     show_fan_full_speed,
+                     store_fan_full_speed, 0, 3),
+       SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
+       SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
+       SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
+                     store_pwm_enable, 0, 3),
+       SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
+                     show_pwm_interpolate, store_pwm_interpolate, 0, 3),
+} };
 
-/* Fan / PWM attr for the f71862fg, less pwms and less zones per pwm than the
-   f71882fg */
-static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
+/* Attr for models which can beep on Fan alarm */
+static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
        SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
                store_fan_beep, 0, 0),
        SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
                store_fan_beep, 0, 1),
        SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
                store_fan_beep, 0, 2),
+       SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
+               store_fan_beep, 0, 3),
+};
 
+/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
+   f71858fg / f71882fg / f71889fg */
+static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
+       SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 0),
        SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      1, 0),
@@ -487,6 +501,9 @@ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
        SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
 
+       SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 1),
        SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      1, 1),
@@ -506,6 +523,9 @@ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
        SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
 
+       SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 2),
        SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      1, 2),
@@ -526,8 +546,11 @@ static struct sensor_device_attribute_2 f71862fg_fan_attr[] = {
                      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
 };
 
-/* Fan / PWM attr common to both the f71882fg and f71858fg */
-static struct sensor_device_attribute_2 f71882fg_f71858fg_fan_attr[] = {
+/* PWM attr common to the f71858fg, f71882fg and f71889fg */
+static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
+       SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 0),
        SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      0, 0),
@@ -565,7 +588,10 @@ static struct sensor_device_attribute_2 f71882fg_f71858fg_fan_attr[] = {
                      show_pwm_auto_point_temp_hyst, NULL, 2, 0),
        SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
-
+}, {
+       SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 1),
        SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      0, 1),
@@ -603,7 +629,10 @@ static struct sensor_device_attribute_2 f71882fg_f71858fg_fan_attr[] = {
                      show_pwm_auto_point_temp_hyst, NULL, 2, 1),
        SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
-
+}, {
+       SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 2),
        SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      0, 2),
@@ -641,30 +670,7 @@ static struct sensor_device_attribute_2 f71882fg_f71858fg_fan_attr[] = {
                      show_pwm_auto_point_temp_hyst, NULL, 2, 2),
        SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
-};
-
-/* Fan / PWM attr found on the f71882fg but not on the f71858fg */
-static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
-       SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-               store_fan_beep, 0, 0),
-       SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-               store_fan_beep, 0, 1),
-       SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-               store_fan_beep, 0, 2),
-
-       SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
-       SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR,
-                     show_fan_full_speed,
-                     store_fan_full_speed, 0, 3),
-       SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep,
-               store_fan_beep, 0, 3),
-       SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3),
-
-       SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3),
-       SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable,
-                     store_pwm_enable, 0, 3),
-       SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR,
-                     show_pwm_interpolate, store_pwm_interpolate, 0, 3),
+}, {
        SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_channel,
                      store_pwm_auto_point_channel, 0, 3),
@@ -705,14 +711,20 @@ static struct sensor_device_attribute_2 f71882fg_fan_attr[] = {
                      show_pwm_auto_point_temp_hyst, NULL, 2, 3),
        SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 3),
-};
+} };
 
-/* Fan / PWM attr for the f8000, zones mapped to temp instead of to pwm!
-   Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
-   F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
+/* Fan attr specific to the f8000 (4th fan input can only measure speed) */
 static struct sensor_device_attribute_2 f8000_fan_attr[] = {
        SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3),
+};
 
+/* PWM attr for the f8000, zones mapped to temp instead of to pwm!
+   Also the register block at offset A0 maps to TEMP1 (so our temp2, as the
+   F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 */
+static struct sensor_device_attribute_2 f8000_auto_pwm_attr[] = {
+       SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 0),
        SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      0, 2),
@@ -751,6 +763,9 @@ static struct sensor_device_attribute_2 f8000_fan_attr[] = {
        SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
 
+       SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 1),
        SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      0, 0),
@@ -789,6 +804,9 @@ static struct sensor_device_attribute_2 f8000_fan_attr[] = {
        SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO,
                      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
 
+       SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+                     show_pwm_auto_point_channel,
+                     store_pwm_auto_point_channel, 0, 2),
        SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR,
                      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
                      0, 1),
@@ -929,7 +947,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
        /* Update once every 60 seconds */
        if ( time_after(jiffies, data->last_limits + 60 * HZ ) ||
                        !data->valid) {
-               if (data->type == f71882fg) {
+               if (data->type == f71882fg || data->type == f71889fg) {
                        data->in1_max =
                                f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
                        data->in_beep =
@@ -951,7 +969,8 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
                                                F71882FG_REG_TEMP_HYST(1));
                }
 
-               if (data->type == f71862fg || data->type == f71882fg) {
+               if (data->type == f71862fg || data->type == f71882fg ||
+                   data->type == f71889fg) {
                        data->fan_beep = f71882fg_read8(data,
                                                F71882FG_REG_FAN_BEEP);
                        data->temp_beep = f71882fg_read8(data,
@@ -961,15 +980,33 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
                        data->temp_type[2] = (reg & 0x04) ? 2 : 4;
                        data->temp_type[3] = (reg & 0x08) ? 2 : 4;
                }
-               reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
-               if ((reg2 & 0x03) == 0x01)
-                       data->temp_type[1] = 6 /* PECI */;
-               else if ((reg2 & 0x03) == 0x02)
-                       data->temp_type[1] = 5 /* AMDSI */;
-               else if (data->type == f71862fg || data->type == f71882fg)
-                       data->temp_type[1] = (reg & 0x02) ? 2 : 4;
-               else
-                       data->temp_type[1] = 2; /* Only supports BJT */
+               /* Determine temp index 1 sensor type */
+               if (data->type == f71889fg) {
+                       reg2 = f71882fg_read8(data, F71882FG_REG_START);
+                       switch ((reg2 & 0x60) >> 5) {
+                       case 0x00: /* BJT / Thermistor */
+                               data->temp_type[1] = (reg & 0x02) ? 2 : 4;
+                               break;
+                       case 0x01: /* AMDSI */
+                               data->temp_type[1] = 5;
+                               break;
+                       case 0x02: /* PECI */
+                       case 0x03: /* Ibex Peak ?? Report as PECI for now */
+                               data->temp_type[1] = 6;
+                               break;
+                       }
+               } else {
+                       reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
+                       if ((reg2 & 0x03) == 0x01)
+                               data->temp_type[1] = 6; /* PECI */
+                       else if ((reg2 & 0x03) == 0x02)
+                               data->temp_type[1] = 5; /* AMDSI */
+                       else if (data->type == f71862fg ||
+                                data->type == f71882fg)
+                               data->temp_type[1] = (reg & 0x02) ? 2 : 4;
+                       else /* f71858fg and f8000 only support BJT */
+                               data->temp_type[1] = 2;
+               }
 
                data->pwm_enable = f71882fg_read8(data,
                                                  F71882FG_REG_PWM_ENABLE);
@@ -1046,7 +1083,7 @@ static struct f71882fg_data *f71882fg_update_device(struct device *dev)
                if (data->type == f8000)
                        data->fan[3] = f71882fg_read16(data,
                                                F71882FG_REG_FAN(3));
-               if (data->type == f71882fg)
+               if (data->type == f71882fg || data->type == f71889fg)
                        data->in_status = f71882fg_read8(data,
                                                F71882FG_REG_IN_STATUS);
                for (nr = 0; nr < nr_ins; nr++)
@@ -1764,7 +1801,11 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
        int pwm = to_sensor_dev_attr_2(devattr)->index;
        int point = to_sensor_dev_attr_2(devattr)->nr;
        long val = simple_strtol(buf, NULL, 10) / 1000;
-       val = SENSORS_LIMIT(val, 0, 255);
+
+       if (data->type == f71889fg)
+               val = SENSORS_LIMIT(val, -128, 127);
+       else
+               val = SENSORS_LIMIT(val, 0, 127);
 
        mutex_lock(&data->update_lock);
        f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val);
@@ -1794,6 +1835,15 @@ static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev,
        return 0;
 }
 
+static void f71882fg_remove_sysfs_files(struct platform_device *pdev,
+       struct sensor_device_attribute_2 *attr, int count)
+{
+       int i;
+
+       for (i = 0; i < count; i++)
+               device_remove_file(&pdev->dev, &attr[i].dev_attr);
+}
+
 static int __devinit f71882fg_probe(struct platform_device *pdev)
 {
        struct f71882fg_data *data;
@@ -1846,16 +1896,17 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                                        ARRAY_SIZE(f71858fg_in_temp_attr));
                        break;
                case f71882fg:
+               case f71889fg:
                        err = f71882fg_create_sysfs_files(pdev,
-                                       f71882fg_in_temp_attr,
-                                       ARRAY_SIZE(f71882fg_in_temp_attr));
+                                       fxxxx_in1_alarm_attr,
+                                       ARRAY_SIZE(fxxxx_in1_alarm_attr));
                        if (err)
                                goto exit_unregister_sysfs;
                        /* fall through! */
                case f71862fg:
                        err = f71882fg_create_sysfs_files(pdev,
-                                       f718x2fg_in_temp_attr,
-                                       ARRAY_SIZE(f718x2fg_in_temp_attr));
+                                       fxxxx_in_temp_attr,
+                                       ARRAY_SIZE(fxxxx_in_temp_attr));
                        break;
                case f8000:
                        err = f71882fg_create_sysfs_files(pdev,
@@ -1883,6 +1934,7 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                        err = (data->pwm_enable & 0x15) != 0x15;
                        break;
                case f71882fg:
+               case f71889fg:
                        err = 0;
                        break;
                case f8000:
@@ -1897,34 +1949,55 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
                        goto exit_unregister_sysfs;
                }
 
-               err = f71882fg_create_sysfs_files(pdev, fxxxx_fan_attr,
-                                       ARRAY_SIZE(fxxxx_fan_attr));
+               err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
+                               ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
                if (err)
                        goto exit_unregister_sysfs;
 
-               switch (data->type) {
-               case f71862fg:
-                       err = f71882fg_create_sysfs_files(pdev,
-                                       f71862fg_fan_attr,
-                                       ARRAY_SIZE(f71862fg_fan_attr));
-                       break;
-               case f71882fg:
+               if (data->type == f71862fg || data->type == f71882fg ||
+                   data->type == f71889fg) {
                        err = f71882fg_create_sysfs_files(pdev,
-                                       f71882fg_fan_attr,
-                                       ARRAY_SIZE(f71882fg_fan_attr));
+                                       fxxxx_fan_beep_attr, nr_fans);
                        if (err)
                                goto exit_unregister_sysfs;
-                       /* fall through! */
-               case f71858fg:
+               }
+
+               switch (data->type) {
+               case f71862fg:
                        err = f71882fg_create_sysfs_files(pdev,
-                                       f71882fg_f71858fg_fan_attr,
-                                       ARRAY_SIZE(f71882fg_f71858fg_fan_attr));
+                                       f71862fg_auto_pwm_attr,
+                                       ARRAY_SIZE(f71862fg_auto_pwm_attr));
                        break;
                case f8000:
                        err = f71882fg_create_sysfs_files(pdev,
                                        f8000_fan_attr,
                                        ARRAY_SIZE(f8000_fan_attr));
+                       if (err)
+                               goto exit_unregister_sysfs;
+                       err = f71882fg_create_sysfs_files(pdev,
+                                       f8000_auto_pwm_attr,
+                                       ARRAY_SIZE(f8000_auto_pwm_attr));
                        break;
+               case f71889fg:
+                       for (i = 0; i < nr_fans; i++) {
+                               data->pwm_auto_point_mapping[i] =
+                                       f71882fg_read8(data,
+                                               F71882FG_REG_POINT_MAPPING(i));
+                               if (data->pwm_auto_point_mapping[i] & 0x80)
+                                       break;
+                       }
+                       if (i != nr_fans) {
+                               dev_warn(&pdev->dev,
+                                        "Auto pwm controlled by raw digital "
+                                        "data, disabling pwm auto_point "
+                                        "sysfs attributes\n");
+                               break;
+                       }
+                       /* fall through */
+               default: /* f71858fg / f71882fg */
+                       err = f71882fg_create_sysfs_files(pdev,
+                               &fxxxx_auto_pwm_attr[0][0],
+                               ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
                }
                if (err)
                        goto exit_unregister_sysfs;
@@ -1954,33 +2027,76 @@ exit_free:
 
 static int f71882fg_remove(struct platform_device *pdev)
 {
-       int i;
        struct f71882fg_data *data = platform_get_drvdata(pdev);
+       int nr_fans = (data->type == f71882fg) ? 4 : 3;
+       u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
 
        platform_set_drvdata(pdev, NULL);
        if (data->hwmon_dev)
                hwmon_device_unregister(data->hwmon_dev);
 
-       /* Note we are not looping over all attr arrays we have as the ones
-          below are supersets of the ones skipped. */
        device_remove_file(&pdev->dev, &dev_attr_name);
 
-       for (i = 0; i < ARRAY_SIZE(f718x2fg_in_temp_attr); i++)
-               device_remove_file(&pdev->dev,
-                                       &f718x2fg_in_temp_attr[i].dev_attr);
-
-       for (i = 0; i < ARRAY_SIZE(f71882fg_in_temp_attr); i++)
-               device_remove_file(&pdev->dev,
-                                       &f71882fg_in_temp_attr[i].dev_attr);
+       if (start_reg & 0x01) {
+               switch (data->type) {
+               case f71858fg:
+                       if (data->temp_config & 0x10)
+                               f71882fg_remove_sysfs_files(pdev,
+                                       f8000_in_temp_attr,
+                                       ARRAY_SIZE(f8000_in_temp_attr));
+                       else
+                               f71882fg_remove_sysfs_files(pdev,
+                                       f71858fg_in_temp_attr,
+                                       ARRAY_SIZE(f71858fg_in_temp_attr));
+                       break;
+               case f71882fg:
+               case f71889fg:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       fxxxx_in1_alarm_attr,
+                                       ARRAY_SIZE(fxxxx_in1_alarm_attr));
+                       /* fall through! */
+               case f71862fg:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       fxxxx_in_temp_attr,
+                                       ARRAY_SIZE(fxxxx_in_temp_attr));
+                       break;
+               case f8000:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       f8000_in_temp_attr,
+                                       ARRAY_SIZE(f8000_in_temp_attr));
+                       break;
+               }
+       }
 
-       for (i = 0; i < ARRAY_SIZE(fxxxx_fan_attr); i++)
-               device_remove_file(&pdev->dev, &fxxxx_fan_attr[i].dev_attr);
+       if (start_reg & 0x02) {
+               f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
+                               ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
 
-       for (i = 0; i < ARRAY_SIZE(f71882fg_fan_attr); i++)
-               device_remove_file(&pdev->dev, &f71882fg_fan_attr[i].dev_attr);
+               if (data->type == f71862fg || data->type == f71882fg ||
+                   data->type == f71889fg)
+                       f71882fg_remove_sysfs_files(pdev,
+                                       fxxxx_fan_beep_attr, nr_fans);
 
-       for (i = 0; i < ARRAY_SIZE(f8000_fan_attr); i++)
-               device_remove_file(&pdev->dev, &f8000_fan_attr[i].dev_attr);
+               switch (data->type) {
+               case f71862fg:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       f71862fg_auto_pwm_attr,
+                                       ARRAY_SIZE(f71862fg_auto_pwm_attr));
+                       break;
+               case f8000:
+                       f71882fg_remove_sysfs_files(pdev,
+                                       f8000_fan_attr,
+                                       ARRAY_SIZE(f8000_fan_attr));
+                       f71882fg_remove_sysfs_files(pdev,
+                                       f8000_auto_pwm_attr,
+                                       ARRAY_SIZE(f8000_auto_pwm_attr));
+                       break;
+               default: /* f71858fg / f71882fg / f71889fg */
+                       f71882fg_remove_sysfs_files(pdev,
+                               &fxxxx_auto_pwm_attr[0][0],
+                               ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
+               }
+       }
 
        kfree(data);
 
@@ -2012,11 +2128,15 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address,
        case SIO_F71882_ID:
                sio_data->type = f71882fg;
                break;
+       case SIO_F71889_ID:
+               sio_data->type = f71889fg;
+               break;
        case SIO_F8000_ID:
                sio_data->type = f8000;
                break;
        default:
-               printk(KERN_INFO DRVNAME ": Unsupported Fintek device\n");
+               printk(KERN_INFO DRVNAME ": Unsupported Fintek device: %04x\n",
+                      (unsigned int)devid);
                goto exit;
        }
 
index e2107e533ede3371aeff3e4213bac1e06c624dfb..40dfbcd3f3f2f704240a9ab957355208dfb39308 100644 (file)
@@ -681,30 +681,20 @@ static int f75375_detect(struct i2c_client *client, int kind,
                         struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
-       u8 version = 0;
-       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;
-               }
-       }
+       u16 vendid, chipid;
+       u8 version;
+       const char *name;
 
-       if (kind == f75375) {
+       vendid = f75375_read16(client, F75375_REG_VENDOR);
+       chipid = f75375_read16(client, F75375_CHIP_ID);
+       if (chipid == 0x0306 && vendid == 0x1934)
                name = "f75375";
-       } else if (kind == f75373) {
+       else if (chipid == 0x0204 && vendid == 0x1934)
                name = "f75373";
-       }
+       else
+               return -ENODEV;
+
+       version = f75375_read8(client, F75375_REG_VERSION);
        dev_info(&adapter->dev, "found %s version: %02X\n", name, version);
        strlcpy(info->type, name, I2C_NAME_SIZE);
 
index da1b1f9488afc335c60b1833ee3fb7d89d3b832d..281829cd1533824b62b12d66d7c7e78c7c5b7623 100644 (file)
@@ -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)
 {
+       enum chips kind;
        struct i2c_adapter *adapter = client->adapter;
+       char id[4];
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
        /* Detect & Identify the chip */
-       if (kind <= 0) {
-               char id[4];
-
-               id[0] = i2c_smbus_read_byte_data(client,
-                               FSCHMD_REG_IDENT_0);
-               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[3] = '\0';
-
-               if (!strcmp(id, "PEG"))
-                       kind = fscpos;
-               else if (!strcmp(id, "HER"))
-                       kind = fscher;
-               else if (!strcmp(id, "SCY"))
-                       kind = fscscy;
-               else if (!strcmp(id, "HRC"))
-                       kind = fschrc;
-               else if (!strcmp(id, "HMD"))
-                       kind = fschmd;
-               else if (!strcmp(id, "HDS"))
-                       kind = fschds;
-               else if (!strcmp(id, "SYL"))
-                       kind = fscsyl;
-               else
-                       return -ENODEV;
-       }
+       id[0] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_0);
+       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[3] = '\0';
+
+       if (!strcmp(id, "PEG"))
+               kind = fscpos;
+       else if (!strcmp(id, "HER"))
+               kind = fscher;
+       else if (!strcmp(id, "SCY"))
+               kind = fscscy;
+       else if (!strcmp(id, "HRC"))
+               kind = fschrc;
+       else if (!strcmp(id, "HMD"))
+               kind = fschmd;
+       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);
 
index 7820df45d77a7dd56312b890b2756c6bb2c8560c..1d69458aa0b641cab7da8c51f9b7f1825dd0a6a8 100644 (file)
@@ -488,36 +488,21 @@ static int gl518_detect(struct i2c_client *client, int kind,
                        struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
-       int i;
+       int rev;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                     I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
 
        /* Now, we do the remaining detection. */
-
-       if (kind < 0) {
-               if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80)
-                || (gl518_read_value(client, GL518_REG_CONF) & 0x80))
-                       return -ENODEV;
-       }
+       if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80)
+        || (gl518_read_value(client, GL518_REG_CONF) & 0x80))
+               return -ENODEV;
 
        /* Determine the chip type. */
-       if (kind <= 0) {
-               i = gl518_read_value(client, GL518_REG_REVISION);
-               if (i == 0x00) {
-                       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;
-               }
-       }
+       rev = gl518_read_value(client, GL518_REG_REVISION);
+       if (rev != 0x00 && rev != 0x80)
+               return -ENODEV;
 
        strlcpy(info->type, "gl518sm", I2C_NAME_SIZE);
 
index 19616f2242b02ce9b0b51445854d47a2c815b542..92b5720ceaffd57bdece90ce14bcfd37dfdf7888 100644 (file)
@@ -691,13 +691,11 @@ static int gl520_detect(struct i2c_client *client, int kind,
                return -ENODEV;
 
        /* Determine the chip type. */
-       if (kind < 0) {
-               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_CONF) & 0x80) != 0x00)) {
-                       dev_dbg(&client->dev, "Unknown chip type, skipping\n");
-                       return -ENODEV;
-               }
+       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_CONF) & 0x80) != 0x00)) {
+               dev_dbg(&client->dev, "Unknown chip type, skipping\n");
+               return -ENODEV;
        }
 
        strlcpy(info->type, "gl520sm", I2C_NAME_SIZE);
index a3749cb0f181ec623a4d628ea615c66a154a6c5e..0ffe84d190bbfabae0b7343ba6f3d39c078eabee 100644 (file)
@@ -124,6 +124,8 @@ superio_exit(void)
 #define IT87_BASE_REG 0x60
 
 /* 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_VID_REG       0xfc    /* VID value */
 
@@ -244,7 +246,9 @@ struct it87_sio_data {
        /* Values read from Super-I/O config space */
        u8 revision;
        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;
 };
 
@@ -1028,11 +1032,35 @@ static int __init it87_find(unsigned short *address,
                chip_type, *address, sio_data->revision);
 
        /* 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;
 
                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);
 
                reg = superio_inb(IT87_SIO_PINX2_REG);
@@ -1236,8 +1264,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
                }
        }
 
-       if (data->type == it8712 || data->type == it8716
-        || data->type == it8718 || data->type == it8720) {
+       if (!sio_data->skip_vid) {
                data->vrm = vid_which_vrm();
                /* VID reading from Super-I/O config space if available */
                data->vid = sio_data->vid_value;
@@ -1355,8 +1382,10 @@ static int __devinit it87_check_pwm(struct device *dev)
 /* Called when we have found a new IT87. */
 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);
        int tmp, i;
+       u8 mask;
 
        /* initialize to sane defaults:
         * - 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)
        }
 
        /* 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);
-       if ((data->fan_main_ctrl & 0x70) == 0) {
+       if ((data->fan_main_ctrl & mask) == 0) {
                /* 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);
        }
        data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
@@ -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
         * other mode registers */
        for (i = 0; i < 3; i++) {
index 3195a265f0e9e6d2e44985a6cbdce19655fb4f33..5da66ab04f74d6e5abb05fa2468b25859d55b6c9 100644 (file)
@@ -427,40 +427,34 @@ static int lm63_detect(struct i2c_client *new_client, int kind,
                       struct i2c_board_info *info)
 {
        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))
                return -ENODEV;
 
-       if (kind < 0) { /* must identify */
-               u8 man_id, chip_id, reg_config1, reg_config2;
-               u8 reg_alert_status, reg_alert_mask;
-
-               man_id = i2c_smbus_read_byte_data(new_client,
-                        LM63_REG_MAN_ID);
-               chip_id = i2c_smbus_read_byte_data(new_client,
-                         LM63_REG_CHIP_ID);
-               reg_config1 = i2c_smbus_read_byte_data(new_client,
-                             LM63_REG_CONFIG1);
-               reg_config2 = i2c_smbus_read_byte_data(new_client,
-                             LM63_REG_CONFIG2);
-               reg_alert_status = i2c_smbus_read_byte_data(new_client,
-                                  LM63_REG_ALERT_STATUS);
-               reg_alert_mask = i2c_smbus_read_byte_data(new_client,
-                                LM63_REG_ALERT_MASK);
-
-               if (man_id == 0x01 /* National Semiconductor */
-                && chip_id == 0x41 /* LM63 */
-                && (reg_config1 & 0x18) == 0x00
-                && (reg_config2 & 0xF8) == 0x00
-                && (reg_alert_status & 0x20) == 0x00
-                && (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;
-               }
+       man_id = i2c_smbus_read_byte_data(new_client, LM63_REG_MAN_ID);
+       chip_id = i2c_smbus_read_byte_data(new_client, LM63_REG_CHIP_ID);
+
+       reg_config1 = i2c_smbus_read_byte_data(new_client,
+                     LM63_REG_CONFIG1);
+       reg_config2 = i2c_smbus_read_byte_data(new_client,
+                     LM63_REG_CONFIG2);
+       reg_alert_status = i2c_smbus_read_byte_data(new_client,
+                          LM63_REG_ALERT_STATUS);
+       reg_alert_mask = i2c_smbus_read_byte_data(new_client,
+                        LM63_REG_ALERT_MASK);
+
+       if (man_id != 0x01 /* National Semiconductor */
+        || chip_id != 0x41 /* LM63 */
+        || (reg_config1 & 0x18) != 0x00
+        || (reg_config2 & 0xF8) != 0x00
+        || (reg_alert_status & 0x20) != 0x00
+        || (reg_alert_mask & 0xA4) != 0xA4) {
+               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);
diff --git a/drivers/hwmon/lm73.c b/drivers/hwmon/lm73.c
new file mode 100644 (file)
index 0000000..0bf8b2a
--- /dev/null
@@ -0,0 +1,205 @@
+/*
+ * 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);
index 55bd87c15c9a56bf55971ab31d4173fe1b6842d9..e392548cccb8c8c399ab44b511c9b40c197fef53 100644 (file)
@@ -239,6 +239,7 @@ static int lm75_detect(struct i2c_client *new_client, int kind,
 {
        struct i2c_adapter *adapter = new_client->adapter;
        int i;
+       int cur, conf, hyst, os;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                     I2C_FUNC_SMBUS_WORD_DATA))
@@ -251,40 +252,35 @@ static int lm75_detect(struct i2c_client *new_client, int kind,
           The cycling+unused addresses combination is not tested,
           since it would significantly slow the detection down and would
           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 */
-               if (conf & 0xe0)
-                       return -ENODEV;
+       /* 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;
 
-               /* Addresses cycling */
-               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;
+       /* Unused bits */
+       if (conf & 0xe0)
+               return -ENODEV;
+
+       /* Addresses cycling */
+       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);
 
        return 0;
index 866b401ab6e86937f5880d9b7571df72081e9665..ac067fd1948212a42d3972696dbccc771238da05 100644 (file)
@@ -249,6 +249,7 @@ static int lm77_detect(struct i2c_client *new_client, int kind,
                       struct i2c_board_info *info)
 {
        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 |
                                     I2C_FUNC_SMBUS_WORD_DATA))
@@ -265,51 +266,48 @@ static int lm77_detect(struct i2c_client *new_client, int kind,
           4. registers cycling over 8-address boundaries
 
           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 */
-               if (conf & 0xe0)
+       /* 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;
+       }
 
-               /* 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;
+       /* 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 */
+       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);
 
index f7e70163e016a215429aff63819172147cb2104a..5978291cebb370f63965e510947d48d0fa480e65 100644 (file)
@@ -576,52 +576,34 @@ static int lm78_i2c_detect(struct i2c_client *client, int kind,
        if (isa)
                mutex_lock(&isa->update_lock);
 
-       if (kind < 0) {
-               if ((i2c_smbus_read_byte_data(client, LM78_REG_CONFIG) & 0x80)
-                || i2c_smbus_read_byte_data(client, LM78_REG_I2C_ADDR)
-                   != address)
-                       goto err_nodev;
-
-               /* Explicitly prevent the misdetection of Winbond chips */
-               i = i2c_smbus_read_byte_data(client, 0x4f);
-               if (i == 0xa3 || i == 0x5c)
-                       goto err_nodev;
-       }
+       if ((i2c_smbus_read_byte_data(client, LM78_REG_CONFIG) & 0x80)
+        || i2c_smbus_read_byte_data(client, LM78_REG_I2C_ADDR) != address)
+               goto err_nodev;
+
+       /* Explicitly prevent the misdetection of Winbond chips */
+       i = i2c_smbus_read_byte_data(client, 0x4f);
+       if (i == 0xa3 || i == 0x5c)
+               goto err_nodev;
 
        /* Determine the chip type. */
-       if (kind <= 0) {
-               i = i2c_smbus_read_byte_data(client, LM78_REG_CHIPID);
-               if (i == 0x00 || i == 0x20      /* LM78 */
-                || i == 0x40)                  /* LM78-J */
-                       kind = lm78;
-               else if ((i & 0xfe) == 0xc0)
-                       kind = lm79;
-               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), address);
-                       goto err_nodev;
-               }
+       i = i2c_smbus_read_byte_data(client, LM78_REG_CHIPID);
+       if (i == 0x00 || i == 0x20      /* LM78 */
+        || i == 0x40)                  /* LM78-J */
+               client_name = "lm78";
+       else if ((i & 0xfe) == 0xc0)
+               client_name = "lm79";
+       else
+               goto err_nodev;
 
-               if (lm78_alias_detect(client, i)) {
-                       dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
-                               "be the same as ISA device\n", address);
-                       goto err_nodev;
-               }
+       if (lm78_alias_detect(client, i)) {
+               dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
+                       "be the same as ISA device\n", address);
+               goto err_nodev;
        }
 
        if (isa)
                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);
 
        return 0;
index e59e2d1f080c9ba1ee279fb5f7cfba925672c295..08b03e6ed0b7adf3a21aab5ac42c4062982fa767 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm83.c - Part of lm_sensors, Linux kernel modules for hardware
  *          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
  * 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,
                       struct i2c_board_info *info)
 {
        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))
                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, LM83).
-        * 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 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;
-               }
+       /* Detection */
+       if ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1) & 0xA8) ||
+           (i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2) & 0x48) ||
+           (i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41)) {
+               dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n",
+                       new_client->addr);
+               return -ENODEV;
        }
 
-       if (kind <= 0) { /* identification */
-               u8 man_id, chip_id;
-
-               man_id = i2c_smbus_read_byte_data(new_client,
-                   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;
-               }
-       }
+       /* Identification */
+       man_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_MAN_ID);
+       if (man_id != 0x01)     /* National Semiconductor */
+               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";
-       } else
-       if (kind == lm82) {
+               break;
+       case 0x01:
                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);
index 6c53d987de1088dc5f4a199b6a0c44236b220ac4..d56da2e747080b210b907f0291795f93755bd135 100644 (file)
@@ -5,7 +5,7 @@
     Copyright (c) 2002, 2003  Philip Pokorny <ppokorny@penguincomputing.com>
     Copyright (c) 2003        Margit Schubert-While <margitsw@t-online.de>
     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>
 
@@ -1162,107 +1162,80 @@ static int lm85_detect(struct i2c_client *client, int kind,
        struct i2c_adapter *adapter = client->adapter;
        int address = client->addr;
        const char *type_name;
+       int company, verstep;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                /* We need to be able to do byte I/O */
                return -ENODEV;
        }
 
-       /* If auto-detecting, determine the chip type */
-       if (kind < 0) {
-               int company = lm85_read_value(client, LM85_REG_COMPANY);
-               int verstep = lm85_read_value(client, LM85_REG_VERSTEP);
-
-               dev_dbg(&adapter->dev, "Detecting device at 0x%02x with "
-                       "COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
-                       address, company, verstep);
-
-               /* All supported chips have the version in common */
-               if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC &&
-                   (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) {
-                       dev_dbg(&adapter->dev, "Autodetection failed: "
-                               "unsupported version\n");
-                       return -ENODEV;
-               }
-               kind = any_chip;
-
-               /* Now, refine the detection */
-               if (company == LM85_COMPANY_NATIONAL) {
-                       switch (verstep) {
-                       case LM85_VERSTEP_LM85C:
-                               kind = lm85c;
-                               break;
-                       case LM85_VERSTEP_LM85B:
-                               kind = lm85b;
-                               break;
-                       case LM85_VERSTEP_LM96000_1:
-                       case LM85_VERSTEP_LM96000_2:
-                               /* Check for Winbond WPCD377I */
-                               if (lm85_is_fake(client)) {
-                                       dev_dbg(&adapter->dev,
-                                               "Found Winbond WPCD377I, "
-                                               "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;
+       /* Determine the chip type */
+       company = lm85_read_value(client, LM85_REG_COMPANY);
+       verstep = lm85_read_value(client, LM85_REG_VERSTEP);
+
+       dev_dbg(&adapter->dev, "Detecting device at 0x%02x with "
+               "COMPANY: 0x%02x and VERSTEP: 0x%02x\n",
+               address, company, verstep);
+
+       /* All supported chips have the version in common */
+       if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC &&
+           (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) {
+               dev_dbg(&adapter->dev,
+                       "Autodetection failed: unsupported version\n");
+               return -ENODEV;
+       }
+       type_name = "lm85";
+
+       /* Now, refine the detection */
+       if (company == LM85_COMPANY_NATIONAL) {
+               switch (verstep) {
+               case LM85_VERSTEP_LM85C:
+                       type_name = "lm85c";
+                       break;
+               case LM85_VERSTEP_LM85B:
+                       type_name = "lm85b";
+                       break;
+               case LM85_VERSTEP_LM96000_1:
+               case LM85_VERSTEP_LM96000_2:
+                       /* Check for Winbond WPCD377I */
+                       if (lm85_is_fake(client)) {
+                               dev_dbg(&adapter->dev,
+                                       "Found Winbond WPCD377I, ignoring\n");
+                               return -ENODEV;
                        }
-               } else {
-                       dev_dbg(&adapter->dev, "Autodetection failed: "
-                               "unknown vendor\n");
-                       return -ENODEV;
+                       break;
+               }
+       } else if (company == LM85_COMPANY_ANALOG_DEV) {
+               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);
 
        return 0;
index 2e4a3cea95f7e957024d97af9f103551661bdcff..4929b1815eee47ee1a4c30b89d111b6eb0c468f8 100644 (file)
@@ -666,37 +666,32 @@ static int lm87_detect(struct i2c_client *new_client, int kind,
                       struct i2c_board_info *info)
 {
        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))
                return -ENODEV;
 
-       /* Default to an LM87 if forced */
-       if (kind == 0)
-               kind = lm87;
+       if (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)
+               return -ENODEV;
 
        /* Now, we do the remaining detection. */
-       if (kind < 0) {
-               u8 cid = lm87_read_value(new_client, LM87_REG_COMPANY_ID);
-               u8 rev = lm87_read_value(new_client, LM87_REG_REVISION);
-
-               if (cid == 0x02                 /* National Semiconductor */
-                && (rev >= 0x01 && rev <= 0x08))
-                       kind = lm87;
-               else if (cid == 0x41            /* Analog Devices */
-                     && (rev & 0xf0) == 0x10)
-                       kind = adm1024;
-
-               if (kind < 0
-                || (lm87_read_value(new_client, LM87_REG_CONFIG) & 0x80)) {
-                       dev_dbg(&adapter->dev,
-                               "LM87 detection failed at 0x%02x.\n",
-                               new_client->addr);
-                       return -ENODEV;
-               }
+       cid = lm87_read_value(new_client, LM87_REG_COMPANY_ID);
+       rev = lm87_read_value(new_client, LM87_REG_REVISION);
+
+       if (cid == 0x02                 /* National Semiconductor */
+        && (rev >= 0x01 && rev <= 0x08))
+               name = "lm87";
+       else if (cid == 0x41            /* Analog Devices */
+             && (rev & 0xf0) == 0x10)
+               name = "adm1024";
+       else {
+               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;
 }
index 1aff7575799d57d2ad5837c54c46bd8d5a65fd1a..b7c905f50ed437da556ebd37007b3b8440cb23b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * lm90.c - Part of lm_sensors, Linux kernel modules for hardware
  *          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
  * 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,
 {
        struct i2c_adapter *adapter = new_client->adapter;
        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))
                return -ENODEV;
 
-       /*
-        * 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. 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,
+       /* detection and identification */
+       if ((man_id = i2c_smbus_read_byte_data(new_client,
                                                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
-                || (reg_config1 = i2c_smbus_read_byte_data(new_client,
+        || (reg_config1 = i2c_smbus_read_byte_data(new_client,
                                                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)
+               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;
-               
-               if ((address == 0x4C || address == 0x4D)
-                && man_id == 0x01) { /* National Semiconductor */
-                       int reg_config2;
-
-                       if ((reg_config2 = i2c_smbus_read_byte_data(new_client,
-                                               LM90_REG_R_CONFIG2)) < 0)
-                               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;
+
+               if ((reg_config1 & 0x2A) == 0x00
+                && (reg_config2 & 0xF8) == 0x00
+                && reg_convrate <= 0x09) {
+                       if (address == 0x4C
+                        && (chip_id & 0xF0) == 0x20) { /* LM90 */
+                               name = "lm90";
                        } 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) {
-                               kind = max6680;
+                       if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */
+                               name = "lm99";
+                               dev_info(&adapter->dev,
+                                        "Assuming LM99 chip at 0x%02x\n",
+                                        address);
+                               dev_info(&adapter->dev,
+                                        "If it is an LM89, instantiate it "
+                                        "with the new_device sysfs "
+                                        "interface\n");
                        } 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) {
-                               kind = max6646;
+                       if (address == 0x4C
+                        && (chip_id & 0xF0) == 0x10) { /* LM86 */
+                               name = "lm86";
                        }
                }
-
-               if (kind <= 0) { /* identification failed */
-                       dev_dbg(&adapter->dev,
-                               "Unsupported chip at 0x%02x (man_id=0x%02X, "
-                               "chip_id=0x%02X)\n", address, man_id, chip_id);
-                       return -ENODEV;
+       } else
+       if ((address == 0x4C || address == 0x4D)
+        && man_id == 0x41) { /* Analog Devices */
+               if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
+                && (reg_config1 & 0x3F) == 0x00
+                && 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 (kind == lm90) {
-               name = "lm90";
-       } else if (kind == adm1032) {
-               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 (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";
+       if (!name) { /* identification failed */
+               dev_dbg(&adapter->dev,
+                       "Unsupported chip at 0x%02x (man_id=0x%02X, "
+                       "chip_id=0x%02X)\n", address, man_id, chip_id);
+               return -ENODEV;
        }
+
        strlcpy(info->type, name, I2C_NAME_SIZE);
 
        return 0;
index b2e00c5a7eec6b015cbfe86023d7a6c8e5b8c1fd..47ac698709dc2e73650820f8305b6e095de74bef 100644 (file)
@@ -323,31 +323,22 @@ static int lm92_detect(struct i2c_client *new_client, int kind,
                       struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = new_client->adapter;
+       u8 config;
+       u16 man_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
                                            | I2C_FUNC_SMBUS_WORD_DATA))
                return -ENODEV;
 
-       /* A negative kind means that the driver was loaded with no force
-          parameter (default), so we must identify the chip. */
-       if (kind < 0) {
-               u8 config = i2c_smbus_read_byte_data(new_client,
-                            LM92_REG_CONFIG);
-               u16 man_id = i2c_smbus_read_word_data(new_client,
-                            LM92_REG_MAN_ID);
-
-               if ((config & 0xe0) == 0x00
-                && 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;
-       }
+       config = i2c_smbus_read_byte_data(new_client, LM92_REG_CONFIG);
+       man_id = i2c_smbus_read_word_data(new_client, LM92_REG_MAN_ID);
+
+       if ((config & 0xe0) == 0x00 && man_id == 0x0180)
+               pr_info("lm92: Found National Semiconductor LM92 chip\n");
+       else if (max6635_check(new_client))
+               pr_info("lm92: Found Maxim MAX6635 chip\n");
+       else
+               return -ENODEV;
 
        strlcpy(info->type, "lm92", I2C_NAME_SIZE);
 
index c48a284b831467b162e39195ff5342ae74244fcc..124dd7cea54cb72c2d94a0ecd9203fdc6047ce72 100644 (file)
@@ -2505,34 +2505,24 @@ static int lm93_detect(struct i2c_client *client, int kind,
                       struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       int mfr, ver;
 
        if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN))
                return -ENODEV;
 
        /* detection */
-       if (kind < 0) {
-               int mfr = lm93_read_byte(client, LM93_REG_MFR_ID);
-
-               if (mfr != 0x01) {
-                       dev_dbg(&adapter->dev,"detect failed, "
-                               "bad manufacturer id 0x%02x!\n", mfr);
-                       return -ENODEV;
-               }
+       mfr = lm93_read_byte(client, LM93_REG_MFR_ID);
+       if (mfr != 0x01) {
+               dev_dbg(&adapter->dev,
+                       "detect failed, bad manufacturer id 0x%02x!\n", mfr);
+               return -ENODEV;
        }
 
-       if (kind <= 0) {
-               int ver = lm93_read_byte(client, LM93_REG_VER);
-
-               if ((ver == LM93_MFR_ID) || (ver == LM93_MFR_ID_PROTOTYPE)) {
-                       kind = lm93;
-               } 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;
-               }
+       ver = lm93_read_byte(client, LM93_REG_VER);
+       if (ver != LM93_MFR_ID && ver != LM93_MFR_ID_PROTOTYPE) {
+               dev_dbg(&adapter->dev,
+                       "detect failed, bad version id 0x%02x!\n", ver);
+               return -ENODEV;
        }
 
        strlcpy(info->type, "lm93", I2C_NAME_SIZE);
index e34f9e402a2c259ecffc377958735189d952caaa..906b896cf1d0fa6616ce5a8750f54f8e1937bf75 100644 (file)
@@ -315,51 +315,23 @@ static int lm95241_detect(struct i2c_client *new_client, int kind,
 {
        struct i2c_adapter *adapter = new_client->adapter;
        int address = new_client->addr;
-       const char *name = "";
+       const char *name;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       /*
-        * 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. 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.
-        */
-       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;
-                       }
-               }
+       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)) {
+               name = "lm95241";
+       } else {
+               dev_dbg(&adapter->dev, "LM95241 detection failed at 0x%02x\n",
+                       address);
+               return -ENODEV;
        }
 
        /* Fill the i2c board info */
-       if (kind == lm95241)
-               name = "lm95241";
        strlcpy(info->type, name, I2C_NAME_SIZE);
        return 0;
 }
index 7897754f3a5c3187a77786325ae3ab875af457fc..7fcf5ff89e7f903b7fee1dc4cfa10ac8769613be 100644 (file)
@@ -226,58 +226,34 @@ static const struct attribute_group max1619_group = {
  */
 
 /* 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_adapter *adapter = new_client->adapter;
-       u8 reg_config=0, reg_convrate=0, reg_status=0;
+       struct i2c_adapter *adapter = client->adapter;
+       u8 reg_config, reg_convrate, reg_status, man_id, chip_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       /*
-        * 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. 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.
-        */
-       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;
-               }
+       /* detection */
+       reg_config = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONFIG);
+       reg_convrate = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONVRATE);
+       reg_status = i2c_smbus_read_byte_data(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",
+                       client->addr);
+               return -ENODEV;
        }
 
-       if (kind <= 0) { /* identification */
-               u8 man_id, chip_id;
-       
-               man_id = i2c_smbus_read_byte_data(new_client,
-                        MAX1619_REG_R_MAN_ID);
-               chip_id = i2c_smbus_read_byte_data(new_client,
-                         MAX1619_REG_R_CHIP_ID);
-               
-               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;
-               }
+       /* identification */
+       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);
+       if (man_id != 0x4D || chip_id != 0x04) {
+               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);
index 58f66be61b1fbb5e91498c87829b8c912cedc5bc..1da561e0cb37dbd6e8e8db112a94b4bdd5893a0b 100644 (file)
@@ -534,7 +534,7 @@ static int max6650_detect(struct i2c_client *client, int kind,
        struct i2c_adapter *adapter = client->adapter;
        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)) {
                dev_dbg(&adapter->dev, "max6650: I2C bus doesn't support "
@@ -542,23 +542,7 @@ static int max6650_detect(struct i2c_client *client, int kind,
                return -ENODEV;
        }
 
-       /*
-        * 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)
+       if (((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_ALARM_EN) & 0xE0)
            ||(i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM) & 0xE0)
diff --git a/drivers/hwmon/mc13783-adc.c b/drivers/hwmon/mc13783-adc.c
new file mode 100644 (file)
index 0000000..883fa81
--- /dev/null
@@ -0,0 +1,236 @@
+/*
+ * 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);
index 71835412529fca92dd4964dc28c95c6c749162be..3f3f9a47acfd92fa473a000f43552047a7e962de 100644 (file)
@@ -323,7 +323,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev)
        }
 
        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)
                        continue;
@@ -333,7 +333,7 @@ static int __devinit s3c_hwmon_probe(struct platform_device *dev)
                                 "channel %d multiplier too large\n",
                                 i);
 
-               if (cfg->divider == 0) {
+               if (cfg->div == 0) {
                        dev_err(&dev->dev, "channel %d divider zero\n", i);
                        continue;
                }
index 8bb5cb532d4d8c121595298729f7b85c03ed3d50..4d88c045781c6cbac9ebebb83037bc9364318adc 100644 (file)
@@ -491,24 +491,22 @@ static int smsc47m192_detect(struct i2c_client *client, int kind,
                return -ENODEV;
 
        /* Detection criteria from sensors_detect script */
-       if (kind < 0) {
-               if (i2c_smbus_read_byte_data(client,
+       version = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VERSION);
+       if (i2c_smbus_read_byte_data(client,
                                SMSC47M192_REG_COMPANY_ID) == 0x55
-                && ((version = i2c_smbus_read_byte_data(client,
-                               SMSC47M192_REG_VERSION)) & 0xf0) == 0x20
-                && (i2c_smbus_read_byte_data(client,
+        && (version & 0xf0) == 0x20
+        && (i2c_smbus_read_byte_data(client,
                                SMSC47M192_REG_VID) & 0x70) == 0x00
-                && (i2c_smbus_read_byte_data(client,
+        && (i2c_smbus_read_byte_data(client,
                                SMSC47M192_REG_VID4) & 0xfe) == 0x80) {
-                       dev_info(&adapter->dev,
-                                "found SMSC47M192 or compatible, "
-                                "version 2, stepping A%d\n", version & 0x0f);
-               } else {
-                       dev_dbg(&adapter->dev,
-                               "SMSC47M192 detection failed at 0x%02x\n",
-                               client->addr);
-                       return -ENODEV;
-               }
+               dev_info(&adapter->dev,
+                        "found SMSC47M192 or compatible, "
+                        "version 2, stepping A%d\n", version & 0x0f);
+       } else {
+               dev_dbg(&adapter->dev,
+                       "SMSC47M192 detection failed at 0x%02x\n",
+                       client->addr);
+               return -ENODEV;
        }
 
        strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE);
index 7d97431e132f2f76fbc22e1e8d693d7c0e58b017..4b793849c73818eb3fd6d5c8cd2aca986d17d514 100644 (file)
@@ -36,7 +36,11 @@ static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
 
 /* Insmod parameters */
 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)");
 
 /* Many THMC50 constants specified below */
@@ -289,7 +293,6 @@ static int thmc50_detect(struct i2c_client *client, int kind,
        unsigned revision;
        unsigned config;
        struct i2c_adapter *adapter = client->adapter;
-       int err = 0;
        const char *type_name;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -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",
                 client->addr, i2c_adapter_id(client->adapter));
 
-       /* Now, we do the remaining detection. */
        company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID);
        revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE);
        config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+       if (revision < 0xc0 || (config & 0x10))
+               return -ENODEV;
 
-       if (kind == 0)
-               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) {
+       if (company == 0x41) {
                int id = i2c_adapter_id(client->adapter);
                int i;
 
@@ -340,9 +325,13 @@ static int thmc50_detect(struct i2c_client *client, int kind,
                                                          config);
                                break;
                        }
-       } else {
+       } else if (company == 0x49) {
                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",
                 type_name, (revision >> 4) - 0xc, revision & 0xf);
 
index 7b34f2cd08bbf49258053fcc1b2caacc02867d03..ee9673467c4a7289ac8b0b6313d2ed3a4222a733 100644 (file)
@@ -488,46 +488,43 @@ static void tmp401_init_client(struct i2c_client *client)
                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)
 {
+       enum chips kind;
        struct i2c_adapter *adapter = client->adapter;
+       u8 reg;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
        /* Detect and identify the chip */
-       if (kind <= 0) {
-               u8 reg;
-
-               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_MANUFACTURER_ID_REG);
+       if (reg != TMP401_MANUFACTURER_ID)
+               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_DEVICE_ID_REG);
 
-               reg = i2c_smbus_read_byte_data(client,
-                                              TMP401_CONVERSION_RATE_READ);
-               /* Datasheet says: 0x1-0x6 */
-               if (reg > 15)
-                       return -ENODEV;
+       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);
+       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);
 
        return 0;
index 20924343431b65f61048ca2fc05c5b1d93afbcd7..bb5464a289cac8e9b8d3cd5d9a39a98656276ad4 100644 (file)
@@ -223,39 +223,36 @@ static int tmp421_init_client(struct i2c_client *client)
        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)
 {
+       enum chips kind;
        struct i2c_adapter *adapter = client->adapter;
        const char *names[] = { "TMP421", "TMP422", "TMP423" };
+       u8 reg;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       if (kind <= 0) {
-               u8 reg;
-
-               reg = i2c_smbus_read_byte_data(client,
-                                              TMP421_MANUFACTURER_ID_REG);
-               if (reg != TMP421_MANUFACTURER_ID)
-                       return -ENODEV;
-
-               reg = i2c_smbus_read_byte_data(client,
-                                              TMP421_DEVICE_ID_REG);
-               switch (reg) {
-               case TMP421_DEVICE_ID:
-                       kind = tmp421;
-                       break;
-               case TMP422_DEVICE_ID:
-                       kind = tmp422;
-                       break;
-               case TMP423_DEVICE_ID:
-                       kind = tmp423;
-                       break;
-               default:
-                       return -ENODEV;
-               }
+       reg = i2c_smbus_read_byte_data(client, TMP421_MANUFACTURER_ID_REG);
+       if (reg != TMP421_MANUFACTURER_ID)
+               return -ENODEV;
+
+       reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG);
+       switch (reg) {
+       case TMP421_DEVICE_ID:
+               kind = tmp421;
+               break;
+       case TMP422_DEVICE_ID:
+               kind = tmp422;
+               break;
+       case TMP423_DEVICE_ID:
+               kind = tmp423;
+               break;
+       default:
+               return -ENODEV;
        }
+
        strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE);
        dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",
                 names[kind - 1], client->addr);
index 2be28ac4ede0d1d439daa60f8bf581f251cf66b9..b257c7223733c3fa1f9719bf0721bdd79425204c 100644 (file)
@@ -59,10 +59,11 @@ static struct platform_device *pdev;
 #define DRVNAME "w83627hf"
 enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf };
 
-static u16 force_addr;
-module_param(force_addr, ushort, 0);
-MODULE_PARM_DESC(force_addr,
-                "Initialize the base address of the sensors");
+struct w83627hf_sio_data {
+       enum chips type;
+       int sioaddr;
+};
+
 static u8 force_i2c = 0x1f;
 module_param(force_i2c, byte, 0);
 MODULE_PARM_DESC(force_i2c,
@@ -77,9 +78,7 @@ module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
 /* modified from kernel/include/traps.c */
-static int REG;                /* The register to read/write */
 #define        DEV     0x07    /* Register: Logical device select */
-static int VAL;                /* The value to read/write */
 
 /* logical device numbers for superio_select (below) */
 #define W83627HF_LD_FDC                0x00
@@ -109,37 +108,37 @@ static int VAL;           /* The value to read/write */
 #define W83687THF_VID_DATA     0xF1 /* w83687thf only */
 
 static inline void
-superio_outb(int reg, int val)
+superio_outb(struct w83627hf_sio_data *sio, int reg, int val)
 {
-       outb(reg, REG);
-       outb(val, VAL);
+       outb(reg, sio->sioaddr);
+       outb(val, sio->sioaddr + 1);
 }
 
 static inline int
-superio_inb(int reg)
+superio_inb(struct w83627hf_sio_data *sio, int reg)
 {
-       outb(reg, REG);
-       return inb(VAL);
+       outb(reg, sio->sioaddr);
+       return inb(sio->sioaddr + 1);
 }
 
 static inline void
-superio_select(int ld)
+superio_select(struct w83627hf_sio_data *sio, int ld)
 {
-       outb(DEV, REG);
-       outb(ld, VAL);
+       outb(DEV, sio->sioaddr);
+       outb(ld,  sio->sioaddr + 1);
 }
 
 static inline void
-superio_enter(void)
+superio_enter(struct w83627hf_sio_data *sio)
 {
-       outb(0x87, REG);
-       outb(0x87, REG);
+       outb(0x87, sio->sioaddr);
+       outb(0x87, sio->sioaddr);
 }
 
 static inline void
-superio_exit(void)
+superio_exit(struct w83627hf_sio_data *sio)
 {
-       outb(0xAA, REG);
+       outb(0xAA, sio->sioaddr);
 }
 
 #define W627_DEVID 0x52
@@ -380,10 +379,6 @@ struct w83627hf_data {
        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 __devexit w83627hf_remove(struct platform_device *pdev);
@@ -1140,11 +1135,8 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
                "W83687THF",
        };
 
-       REG = sioaddr;
-       VAL = sioaddr + 1;
-
-       superio_enter();
-       val = force_id ? force_id : superio_inb(DEVID);
+       superio_enter(sio_data);
+       val = force_id ? force_id : superio_inb(sio_data, DEVID);
        switch (val) {
        case W627_DEVID:
                sio_data->type = w83627hf;
@@ -1168,16 +1160,9 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
                goto exit;
        }
 
-       superio_select(W83627HF_LD_HWM);
-       force_addr &= WINB_ALIGNMENT;
-       if (force_addr) {
-               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);
+       superio_select(sio_data, W83627HF_LD_HWM);
+       val = (superio_inb(sio_data, WINB_BASE_REG) << 8) |
+              superio_inb(sio_data, WINB_BASE_REG + 1);
        *addr = val & WINB_ALIGNMENT;
        if (*addr == 0) {
                printk(KERN_WARNING DRVNAME ": Base address not set, "
@@ -1185,18 +1170,19 @@ static int __init w83627hf_find(int sioaddr, unsigned short *addr,
                goto exit;
        }
 
-       val = superio_inb(WINB_ACT_REG);
+       val = superio_inb(sio_data, WINB_ACT_REG);
        if (!(val & 0x01)) {
                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;
+       sio_data->sioaddr = sioaddr;
        pr_info(DRVNAME ": Found %s chip at %#x\n",
                names[sio_data->type], *addr);
 
  exit:
-       superio_exit();
+       superio_exit(sio_data);
        return err;
 }
 
@@ -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)
 {
+       struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
        int res = 0xff, sel;
 
-       superio_enter();
-       superio_select(W83627HF_LD_GPIO5);
+       superio_enter(sio_data);
+       superio_select(sio_data, W83627HF_LD_GPIO5);
 
        /* 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");
                goto exit;
        }
 
        /* Make sure the pins are configured for input
           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) {
                dev_dbg(&pdev->dev, "GPIO5 not configured for VID "
                        "function\n");
@@ -1532,37 +1519,38 @@ static int __devinit w83627thf_read_gpio5(struct platform_device *pdev)
        }
 
        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:
-       superio_exit();
+       superio_exit(sio_data);
        return res;
 }
 
 static int __devinit w83687thf_read_vid(struct platform_device *pdev)
 {
+       struct w83627hf_sio_data *sio_data = pdev->dev.platform_data;
        int res = 0xff;
 
-       superio_enter();
-       superio_select(W83627HF_LD_HWM);
+       superio_enter(sio_data);
+       superio_select(sio_data, W83627HF_LD_HWM);
 
        /* 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");
                goto exit;
        }
 
        /* 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, "
                        "no VID function\n");
                goto exit;
        }
 
-       res = superio_inb(W83687THF_VID_DATA) & 0x3f;
+       res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f;
 
 exit:
-       superio_exit();
+       superio_exit(sio_data);
        return res;
 }
 
index d27ed1bac002cd1c35c8c55b41be32253c5a9936..7ab7967da0a0359fe1dca5f90518c927752aedf5 100644 (file)
@@ -1054,11 +1054,11 @@ static int
 w83781d_detect(struct i2c_client *client, int kind,
               struct i2c_board_info *info)
 {
-       int val1 = 0, val2;
+       int val1, val2;
        struct w83781d_data *isa = w83781d_data_if_isa();
        struct i2c_adapter *adapter = client->adapter;
        int address = client->addr;
-       const char *client_name = "";
+       const char *client_name;
        enum vendor { winbond, asus } vendid;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -1070,98 +1070,73 @@ w83781d_detect(struct i2c_client *client, int kind,
        if (isa)
                mutex_lock(&isa->update_lock);
 
-       /* The w8378?d may be stuck in some other bank than bank 0. This may
-          make reading other information impossible. Specify a force=... or
-          force_*=... parameter, and the Winbond will be reset to the right
-          bank. */
-       if (kind < 0) {
-               if (i2c_smbus_read_byte_data
-                   (client, W83781D_REG_CONFIG) & 0x80) {
-                       dev_dbg(&adapter->dev, "Detection of w83781d chip "
-                               "failed at step 3\n");
-                       goto err_nodev;
-               }
-               val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK);
-               val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
-               /* Check for Winbond or Asus ID if in bank 0 */
-               if ((!(val1 & 0x07)) &&
-                   (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3))
-                    || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)))) {
-                       dev_dbg(&adapter->dev, "Detection of w83781d chip "
-                               "failed at step 4\n");
+       if (i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG) & 0x80) {
+               dev_dbg(&adapter->dev,
+                       "Detection of w83781d chip failed at step 3\n");
+               goto err_nodev;
+       }
+
+       val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK);
+       val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
+       /* Check for Winbond or Asus ID if in bank 0 */
+       if (!(val1 & 0x07) &&
+           ((!(val1 & 0x80) && val2 != 0xa3 && val2 != 0xc3) ||
+            ( (val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) {
+               dev_dbg(&adapter->dev,
+                       "Detection of w83781d chip failed at step 4\n");
+               goto err_nodev;
+       }
+       /* If Winbond SMBus, check address at 0x48.
+          Asus doesn't support, except for as99127f rev.2 */
+       if ((!(val1 & 0x80) && val2 == 0xa3) ||
+           ( (val1 & 0x80) && val2 == 0x5c)) {
+               if (i2c_smbus_read_byte_data(client, W83781D_REG_I2C_ADDR)
+                   != address) {
+                       dev_dbg(&adapter->dev,
+                               "Detection of w83781d chip failed at step 5\n");
                        goto err_nodev;
                }
-               /* If Winbond SMBus, check address at 0x48.
-                  Asus doesn't support, except for as99127f rev.2 */
-               if ((!(val1 & 0x80) && (val2 == 0xa3)) ||
-                   ((val1 & 0x80) && (val2 == 0x5c))) {
-                       if (i2c_smbus_read_byte_data
-                           (client, W83781D_REG_I2C_ADDR) != address) {
-                               dev_dbg(&adapter->dev, "Detection of w83781d "
-                                       "chip failed at step 5\n");
-                               goto err_nodev;
-                       }
-               }
        }
 
-       /* We have either had a force parameter, or we have already detected the
-          Winbond. Put it now into bank 0 and Vendor ID High Byte */
+       /* Put it now into bank 0 and Vendor ID High Byte */
        i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
                (i2c_smbus_read_byte_data(client, W83781D_REG_BANK)
                 & 0x78) | 0x80);
 
-       /* Determine the chip type. */
-       if (kind <= 0) {
-               /* get vendor ID */
-               val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
-               if (val2 == 0x5c)
-                       vendid = winbond;
-               else if (val2 == 0x12)
-                       vendid = asus;
-               else {
-                       dev_dbg(&adapter->dev, "w83781d chip vendor is "
-                               "neither Winbond nor Asus\n");
-                       goto err_nodev;
-               }
-
-               val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID);
-               if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
-                       kind = w83781d;
-               else if (val1 == 0x30 && vendid == winbond)
-                       kind = w83782d;
-               else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
-                       kind = w83783s;
-               else if (val1 == 0x31)
-                       kind = as99127f;
-               else {
-                       if (kind == 0)
-                               dev_warn(&adapter->dev, "Ignoring 'force' "
-                                        "parameter for unknown chip at "
-                                        "address 0x%02x\n", address);
-                       goto err_nodev;
-               }
-
-               if ((kind == w83781d || kind == w83782d)
-                && w83781d_alias_detect(client, val1)) {
-                       dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
-                               "be the same as ISA device\n", address);
-                       goto err_nodev;
-               }
+       /* Get the vendor ID */
+       val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN);
+       if (val2 == 0x5c)
+               vendid = winbond;
+       else if (val2 == 0x12)
+               vendid = asus;
+       else {
+               dev_dbg(&adapter->dev,
+                       "w83781d chip vendor is neither Winbond nor Asus\n");
+               goto err_nodev;
        }
 
-       if (isa)
-               mutex_unlock(&isa->update_lock);
-
-       if (kind == w83781d) {
+       /* Determine the chip type. */
+       val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID);
+       if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond)
                client_name = "w83781d";
-       } else if (kind == w83782d) {
+       else if (val1 == 0x30 && vendid == winbond)
                client_name = "w83782d";
-       } else if (kind == w83783s) {
+       else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
                client_name = "w83783s";
-       } else if (kind == as99127f) {
+       else if (val1 == 0x31)
                client_name = "as99127f";
+       else
+               goto err_nodev;
+
+       if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) {
+               dev_dbg(&adapter->dev, "Device at 0x%02x appears to "
+                       "be the same as ISA device\n", address);
+               goto err_nodev;
        }
 
+       if (isa)
+               mutex_unlock(&isa->update_lock);
+
        strlcpy(info->type, client_name, I2C_NAME_SIZE);
 
        return 0;
index 97851c5ba3a3872caa715e130c3ff12a29c55297..0410bf12c5211cbb9bb27116d3dd343726adba8c 100644 (file)
@@ -1270,56 +1270,32 @@ static int w83791d_detect(struct i2c_client *client, int kind,
                return -ENODEV;
        }
 
-       /* The w83791d may be stuck in some other bank than bank 0. This may
-          make reading other information impossible. Specify a force=...
-          parameter, and the Winbond will be reset to the right bank. */
-       if (kind < 0) {
-               if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) {
-                       return -ENODEV;
-               }
-               val1 = w83791d_read(client, W83791D_REG_BANK);
-               val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
-               /* 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) {
+       if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80)
+               return -ENODEV;
+
+       val1 = w83791d_read(client, W83791D_REG_BANK);
+       val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
+       /* Check for Winbond ID if in bank 0 */
+       if (!(val1 & 0x07)) {
+               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;
 
-       /* We either have a force parameter or we have reason to
-          believe it is a Winbond chip. Either way, we want bank 0 and
-          Vendor ID high byte */
+       /* We want bank 0 and Vendor ID high byte */
        val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78;
        w83791d_write(client, W83791D_REG_BANK, val1 | 0x80);
 
        /* Verify it is a Winbond w83791d */
-       if (kind <= 0) {
-               /* get vendor ID */
-               val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
-               if (val2 != 0x5c) {     /* the vendor is NOT Winbond */
-                       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;
-               }
-       }
+       val1 = w83791d_read(client, W83791D_REG_WCHIPID);
+       val2 = w83791d_read(client, W83791D_REG_CHIPMAN);
+       if (val1 != 0x71 || val2 != 0x5c)
+               return -ENODEV;
 
        strlcpy(info->type, "w83791d", I2C_NAME_SIZE);
 
index 2be16194ddf3a980674ea91f111c4437a9890e5b..38978851333f6361cbb62d76d4210c6edf5e4662 100644 (file)
@@ -1273,58 +1273,33 @@ w83792d_detect(struct i2c_client *client, int kind, struct i2c_board_info *info)
                return -ENODEV;
        }
 
-       /* The w83792d may be stuck in some other bank than bank 0. This may
-          make reading other information impossible. Specify a force=... or
-          force_*=... parameter, and the Winbond will be reset to the right
-          bank. */
-       if (kind < 0) {
-               if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) {
-                       return -ENODEV;
-               }
-               val1 = w83792d_read_value(client, W83792D_REG_BANK);
-               val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
-               /* Check for Winbond ID if in bank 0 */
-               if (!(val1 & 0x07)) {  /* is Bank0 */
-                       if (((!(val1 & 0x80)) && (val2 != 0xa3)) ||
-                            ((val1 & 0x80) && (val2 != 0x5c))) {
-                               return -ENODEV;
-                       }
-               }
-               /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
-                  should match */
-               if (w83792d_read_value(client,
-                                       W83792D_REG_I2C_ADDR) != address) {
+       if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80)
+               return -ENODEV;
+
+       val1 = w83792d_read_value(client, W83792D_REG_BANK);
+       val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
+       /* Check for Winbond ID if in bank 0 */
+       if (!(val1 & 0x07)) {  /* is Bank0 */
+               if ((!(val1 & 0x80) && val2 != 0xa3) ||
+                   ( (val1 & 0x80) && val2 != 0x5c))
                        return -ENODEV;
-               }
        }
+       /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
+          should match */
+       if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address)
+               return -ENODEV;
 
-       /* We have either had a force parameter, or we have already detected the
-          Winbond. Put it now into bank 0 and Vendor ID High Byte */
+       /*  Put it now into bank 0 and Vendor ID High Byte */
        w83792d_write_value(client,
                            W83792D_REG_BANK,
                            (w83792d_read_value(client,
                                W83792D_REG_BANK) & 0x78) | 0x80);
 
        /* Determine the chip type. */
-       if (kind <= 0) {
-               /* get vendor ID */
-               val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
-               if (val2 != 0x5c) {  /* the vendor is NOT Winbond */
-                       return -ENODEV;
-               }
-               val1 = w83792d_read_value(client, W83792D_REG_WCHIPID);
-               if (val1 == 0x7a) {
-                       kind = w83792d;
-               } else {
-                       if (kind == 0)
-                               dev_warn(&adapter->dev,
-                                       "w83792d: Ignoring 'force' parameter for"
-                                       " unknown chip at adapter %d, address"
-                                       " 0x%02x\n", i2c_adapter_id(adapter),
-                                       address);
-                       return -ENODEV;
-               }
-       }
+       val1 = w83792d_read_value(client, W83792D_REG_WCHIPID);
+       val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN);
+       if (val1 != 0x7a || val2 != 0x5c)
+               return -ENODEV;
 
        strlcpy(info->type, "w83792d", I2C_NAME_SIZE);
 
index 47dd398f72589ba795abbb11e550e9bb82fd4e00..80a2191bf1274d0b54581113972e669d6be0822d 100644 (file)
@@ -1164,7 +1164,7 @@ ERROR_SC_0:
 static int w83793_detect(struct i2c_client *client, int kind,
                         struct i2c_board_info *info)
 {
-       u8 tmp, bank;
+       u8 tmp, bank, chip_id;
        struct i2c_adapter *adapter = client->adapter;
        unsigned short address = client->addr;
 
@@ -1174,44 +1174,27 @@ static int w83793_detect(struct i2c_client *client, int kind,
 
        bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL);
 
-       if (kind < 0) {
-               tmp = bank & 0x80 ? 0x5c : 0xa3;
-               /* Check Winbond vendor ID */
-               if (tmp != i2c_smbus_read_byte_data(client,
-                                                       W83793_REG_VENDORID)) {
-                       pr_debug("w83793: Detection failed at check "
-                                "vendor id\n");
-                       return -ENODEV;
-               }
-
-               /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
-                  should match */
-               if ((bank & 0x07) == 0
-                && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) !=
-                   (address << 1)) {
-                       pr_debug("w83793: Detection failed at check "
-                                "i2c addr\n");
-                       return -ENODEV;
-               }
-
+       tmp = bank & 0x80 ? 0x5c : 0xa3;
+       /* Check Winbond vendor ID */
+       if (tmp != i2c_smbus_read_byte_data(client, W83793_REG_VENDORID)) {
+               pr_debug("w83793: Detection failed at check vendor id\n");
+               return -ENODEV;
        }
 
-       /* We have either had a force parameter, or we have already detected the
-          Winbond. Determine the chip type now */
-
-       if (kind <= 0) {
-               if (0x7b == i2c_smbus_read_byte_data(client,
-                                                    W83793_REG_CHIPID)) {
-                       kind = w83793;
-               } else {
-                       if (kind == 0)
-                               dev_warn(&adapter->dev, "w83793: Ignoring "
-                                        "'force' parameter for unknown chip "
-                                        "at address 0x%02x\n", address);
-                       return -ENODEV;
-               }
+       /* If Winbond chip, address of chip and W83793_REG_I2C_ADDR
+          should match */
+       if ((bank & 0x07) == 0
+        && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) !=
+           (address << 1)) {
+               pr_debug("w83793: Detection failed at check i2c addr\n");
+               return -ENODEV;
        }
 
+       /* Determine the chip type now */
+       chip_id = i2c_smbus_read_byte_data(client, W83793_REG_CHIPID);
+       if (chip_id != 0x7b)
+               return -ENODEV;
+
        strlcpy(info->type, "w83793", I2C_NAME_SIZE);
 
        return 0;
index ea295b9fc4f48fc91b84d3c1f24ce013b7360d68..9b6c4c10fba75feaca0f8ca872619ad17fb6be7c 100644 (file)
@@ -1,7 +1,7 @@
 /*
  * w83l785ts.c - Part of lm_sensors, Linux kernel modules for hardware
  *               monitoring
- * Copyright (C) 2003-2004  Jean Delvare <khali@linux-fr.org>
+ * Copyright (C) 2003-2009  Jean Delvare <khali@linux-fr.org>
  *
  * Inspired from the lm83 driver. The W83L785TS-S is a sensor chip made
  * by Winbond. It reports a single external temperature with a 1 deg
@@ -146,60 +146,36 @@ static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1);
  */
 
 /* Return 0 if detection is successful, -ENODEV otherwise */
-static int w83l785ts_detect(struct i2c_client *new_client, int kind,
+static int w83l785ts_detect(struct i2c_client *client, int kind,
                            struct i2c_board_info *info)
 {
-       struct i2c_adapter *adapter = new_client->adapter;
+       struct i2c_adapter *adapter = client->adapter;
+       u16 man_id;
+       u8 chip_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                return -ENODEV;
 
-       /*
-        * 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, W83L785TS-S). 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.
-        */
-       if (kind < 0) { /* detection */
-               if (((w83l785ts_read_value(new_client,
-                     W83L785TS_REG_CONFIG, 0) & 0x80) != 0x00)
-                || ((w83l785ts_read_value(new_client,
-                     W83L785TS_REG_TYPE, 0) & 0xFC) != 0x00)) {
-                       dev_dbg(&adapter->dev,
-                               "W83L785TS-S detection failed at 0x%02x.\n",
-                               new_client->addr);
-                       return -ENODEV;
-               }
+       /* detection */
+       if ((w83l785ts_read_value(client, W83L785TS_REG_CONFIG, 0) & 0x80)
+        || (w83l785ts_read_value(client, W83L785TS_REG_TYPE, 0) & 0xFC)) {
+               dev_dbg(&adapter->dev,
+                       "W83L785TS-S detection failed at 0x%02x\n",
+                       client->addr);
+               return -ENODEV;
        }
 
-       if (kind <= 0) { /* identification */
-               u16 man_id;
-               u8 chip_id;
-
-               man_id = (w83l785ts_read_value(new_client,
-                        W83L785TS_REG_MAN_ID1, 0) << 8) +
-                        w83l785ts_read_value(new_client,
-                        W83L785TS_REG_MAN_ID2, 0);
-               chip_id = w83l785ts_read_value(new_client,
-                         W83L785TS_REG_CHIP_ID, 0);
-
-               if (man_id == 0x5CA3) { /* Winbond */
-                       if (chip_id == 0x70) { /* W83L785TS-S */
-                               kind = w83l785ts;                       
-                       }
-               }
-       
-               if (kind <= 0) { /* identification failed */
-                       dev_info(&adapter->dev,
-                                "Unsupported chip (man_id=0x%04X, "
-                                "chip_id=0x%02X).\n", man_id, chip_id);
-                       return -ENODEV;
-               }
+       /* Identification */
+       man_id = (w83l785ts_read_value(client, W83L785TS_REG_MAN_ID1, 0) << 8)
+              + w83l785ts_read_value(client, W83L785TS_REG_MAN_ID2, 0);
+       chip_id = w83l785ts_read_value(client, W83L785TS_REG_CHIP_ID, 0);
+
+       if (man_id != 0x5CA3            /* Winbond */
+        || chip_id != 0x70) {          /* W83L785TS-S */
+               dev_dbg(&adapter->dev,
+                       "Unsupported chip (man_id=0x%04X, chip_id=0x%02X)\n",
+                       man_id, chip_id);
+               return -ENODEV;
        }
 
        strlcpy(info->type, "w83l785ts", I2C_NAME_SIZE);
index badca769f350dde08a4b1f906fa7826393f5812a..27da7d2b15fb6fb82bbd0b60d63637d2dfb55367 100644 (file)
@@ -590,53 +590,31 @@ w83l786ng_detect(struct i2c_client *client, int kind,
                 struct i2c_board_info *info)
 {
        struct i2c_adapter *adapter = client->adapter;
+       u16 man_id;
+       u8 chip_id;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                return -ENODEV;
        }
 
-       /*
-        * 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, W83L786NG). 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.
-        */
-       if (kind < 0) { /* detection */
-               if (((w83l786ng_read_value(client,
-                   W83L786NG_REG_CONFIG) & 0x80) != 0x00)) {
-                       dev_dbg(&adapter->dev,
-                               "W83L786NG detection failed at 0x%02x.\n",
-                               client->addr);
-                       return -ENODEV;
-               }
+       /* Detection */
+       if ((w83l786ng_read_value(client, W83L786NG_REG_CONFIG) & 0x80)) {
+               dev_dbg(&adapter->dev, "W83L786NG detection failed at 0x%02x\n",
+                       client->addr);
+               return -ENODEV;
        }
 
-       if (kind <= 0) { /* identification */
-               u16 man_id;
-               u8 chip_id;
-
-               man_id = (w83l786ng_read_value(client,
-                   W83L786NG_REG_MAN_ID1) << 8) +
-                   w83l786ng_read_value(client, W83L786NG_REG_MAN_ID2);
-               chip_id = w83l786ng_read_value(client, W83L786NG_REG_CHIP_ID);
-
-               if (man_id == 0x5CA3) { /* Winbond */
-                       if (chip_id == 0x80) { /* W83L786NG */
-                               kind = w83l786ng;
-                       }
-               }
+       /* Identification */
+       man_id = (w83l786ng_read_value(client, W83L786NG_REG_MAN_ID1) << 8) +
+                w83l786ng_read_value(client, W83L786NG_REG_MAN_ID2);
+       chip_id = w83l786ng_read_value(client, W83L786NG_REG_CHIP_ID);
 
-               if (kind <= 0) { /* identification failed */
-                       dev_info(&adapter->dev,
-                           "Unsupported chip (man_id=0x%04X, "
-                           "chip_id=0x%02X).\n", man_id, chip_id);
-                       return -ENODEV;
-               }
+       if (man_id != 0x5CA3 ||         /* Winbond */
+           chip_id != 0x80) {          /* W83L786NG */
+               dev_dbg(&adapter->dev,
+                       "Unsupported chip (man_id=0x%04X, chip_id=0x%02X)\n",
+                       man_id, chip_id);
+               return -ENODEV;
        }
 
        strlcpy(info->type, "w83l786ng", I2C_NAME_SIZE);