Merge HEAD from gregkh@master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6.git
author <greg@echidna.(none)> <>
Mon, 5 Sep 2005 16:20:31 +0000 (09:20 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 5 Sep 2005 16:20:31 +0000 (09:20 -0700)
144 files changed:
Documentation/hwmon/lm78
Documentation/hwmon/w83792d [new file with mode: 0644]
Documentation/i2c/chips/max6875
Documentation/i2c/functionality
Documentation/i2c/porting-clients
Documentation/i2c/writing-clients
MAINTAINERS
drivers/hwmon/Kconfig
drivers/hwmon/Makefile
drivers/hwmon/adm1021.c
drivers/hwmon/adm1025.c
drivers/hwmon/adm1026.c
drivers/hwmon/adm1031.c
drivers/hwmon/adm9240.c
drivers/hwmon/asb100.c
drivers/hwmon/atxp1.c
drivers/hwmon/ds1621.c
drivers/hwmon/fscher.c
drivers/hwmon/fscpos.c
drivers/hwmon/gl518sm.c
drivers/hwmon/gl520sm.c
drivers/hwmon/hwmon-vid.c [new file with mode: 0644]
drivers/hwmon/hwmon.c [new file with mode: 0644]
drivers/hwmon/it87.c
drivers/hwmon/lm63.c
drivers/hwmon/lm75.c
drivers/hwmon/lm75.h
drivers/hwmon/lm77.c
drivers/hwmon/lm78.c
drivers/hwmon/lm80.c
drivers/hwmon/lm83.c
drivers/hwmon/lm85.c
drivers/hwmon/lm87.c
drivers/hwmon/lm90.c
drivers/hwmon/lm92.c
drivers/hwmon/max1619.c
drivers/hwmon/pc87360.c
drivers/hwmon/sis5595.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/via686a.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/hwmon/w83792d.c [new file with mode: 0644]
drivers/hwmon/w83l785ts.c
drivers/i2c/Makefile
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-ite.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-sgi.c
drivers/i2c/algos/i2c-algo-sibyte.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isa.c
drivers/i2c/busses/i2c-keywest.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/chips/Kconfig
drivers/i2c/chips/ds1337.c
drivers/i2c/chips/ds1374.c
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/m41t00.c
drivers/i2c/chips/max6875.c
drivers/i2c/chips/pca9539.c
drivers/i2c/chips/pcf8574.c
drivers/i2c/chips/pcf8591.c
drivers/i2c/chips/rtc8564.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/i2c/i2c-sensor-detect.c [deleted file]
drivers/i2c/i2c-sensor-vid.c [deleted file]
drivers/media/common/saa7146_i2c.c
drivers/media/dvb/b2c2/flexcop-i2c.c
drivers/media/dvb/dvb-usb/cxusb.c
drivers/media/dvb/dvb-usb/dibusb-common.c
drivers/media/dvb/dvb-usb/digitv.c
drivers/media/dvb/dvb-usb/dvb-usb-i2c.c
drivers/media/dvb/pluto2/pluto2.c
drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
drivers/media/video/adv7170.c
drivers/media/video/adv7175.c
drivers/media/video/bt819.c
drivers/media/video/bt832.c
drivers/media/video/bt856.c
drivers/media/video/bttv-i2c.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/ir-kbd-i2c.c
drivers/media/video/msp3400.c
drivers/media/video/ovcamchip/ov6x20.c
drivers/media/video/ovcamchip/ov6x30.c
drivers/media/video/ovcamchip/ovcamchip_core.c
drivers/media/video/saa7110.c
drivers/media/video/saa7111.c
drivers/media/video/saa7114.c
drivers/media/video/saa7134/saa6752hs.c
drivers/media/video/saa7134/saa7134-i2c.c
drivers/media/video/saa7185.c
drivers/media/video/tda7432.c
drivers/media/video/tda9840.c
drivers/media/video/tda9875.c
drivers/media/video/tda9887.c
drivers/media/video/tea6415c.c
drivers/media/video/tea6420.c
drivers/media/video/tuner-3036.c
drivers/media/video/tuner-core.c
drivers/media/video/tvaudio.c
drivers/media/video/tveeprom.c
drivers/media/video/tvmixer.c
drivers/media/video/vpx3220.c
drivers/media/video/zoran_card.c
drivers/usb/media/w9968cf.c
drivers/video/aty/radeon_i2c.c
drivers/video/matrox/matroxfb_maven.c
drivers/video/nvidia/nv_i2c.c
drivers/video/riva/rivafb-i2c.c
drivers/video/savage/savagefb-i2c.c
include/linux/hwmon-sysfs.h
include/linux/hwmon-vid.h [new file with mode: 0644]
include/linux/hwmon.h [new file with mode: 0644]
include/linux/i2c-id.h
include/linux/i2c-isa.h [new file with mode: 0644]
include/linux/i2c-sensor.h [deleted file]
include/linux/i2c-vid.h [deleted file]
include/linux/i2c.h
include/media/id.h

index 357086ed7f64e5307506c225f6c3e46db155f932..fd5dc7a19f0e73361ebafb37141071eae77b9c14 100644 (file)
@@ -2,16 +2,11 @@ Kernel driver lm78
 ==================
 
 Supported chips:
-  * National Semiconductor LM78
+  * National Semiconductor LM78 / LM78-J
     Prefix: 'lm78'
     Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
-  * National Semiconductor LM78-J
-    Prefix: 'lm78-j'
-    Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
-    Datasheet: Publicly available at the National Semiconductor website
-               http://www.national.com/
   * National Semiconductor LM79
     Prefix: 'lm79'
     Addresses scanned: I2C 0x20 - 0x2f, ISA 0x290 (8 I/O ports)
diff --git a/Documentation/hwmon/w83792d b/Documentation/hwmon/w83792d
new file mode 100644 (file)
index 0000000..8171c28
--- /dev/null
@@ -0,0 +1,174 @@
+Kernel driver w83792d
+=====================
+
+Supported chips:
+  * Winbond W83792D
+    Prefix: 'w83792d'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: http://www.winbond.com.tw/E-WINBONDHTM/partner/PDFresult.asp?Pname=1035
+
+Author: Chunhao Huang
+Contact: DZShen <DZShen@Winbond.com.tw>
+
+
+Module Parameters
+-----------------
+
+* init int
+  (default 1)
+  Use 'init=0' to bypass initializing the chip.
+  Try this if your computer crashes when you load the module.
+
+* force_subclients=bus,caddr,saddr,saddr
+  This is used to force the i2c addresses for subclients of
+  a certain chip. Example usage is `force_subclients=0,0x2f,0x4a,0x4b'
+  to force the subclients of chip 0x2f on bus 0 to i2c addresses
+  0x4a and 0x4b.
+
+
+Description
+-----------
+
+This driver implements support for the Winbond W83792AD/D.
+
+Detection of the chip can sometimes be foiled because it can be in an
+internal state that allows no clean access (Bank with ID register is not
+currently selected). If you know the address of the chip, use a 'force'
+parameter; this will put it into a more well-behaved state first.
+
+The driver implements three temperature sensors, seven fan rotation speed
+sensors, nine voltage sensors, and two automatic fan regulation
+strategies called: Smart Fan I (Thermal Cruise mode) and Smart Fan II.
+Automatic fan control mode is possible only for fan1-fan3. Fan4-fan7 can run
+synchronized with selected fan (fan1-fan3). This functionality and manual PWM
+control for fan4-fan7 is not yet implemented.
+
+Temperatures are measured in degrees Celsius and measurement resolution is 1
+degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
+the temperature gets higher than the Overtemperature Shutdown value; it stays
+on until the temperature falls below the Hysteresis value.
+
+Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
+triggered if the rotation speed has dropped below a programmable limit. Fan
+readings can be divided by a programmable divider (1, 2, 4, 8, 16, 32, 64 or
+128) to give the readings more range or accuracy.
+
+Voltage sensors (also known as IN sensors) report their values in millivolts.
+An alarm is triggered if the voltage has crossed a programmable minimum
+or maximum limit.
+
+Alarms are provided as output from "realtime status register". Following bits
+are defined:
+
+bit - alarm on:
+0  - in0
+1  - in1
+2  - temp1
+3  - temp2
+4  - temp3
+5  - fan1
+6  - fan2
+7  - fan3
+8  - in2
+9  - in3
+10 - in4
+11 - in5
+12 - in6
+13 - VID change
+14 - chassis
+15 - fan7
+16 - tart1
+17 - tart2
+18 - tart3
+19 - in7
+20 - in8
+21 - fan4
+22 - fan5
+23 - fan6
+
+Tart will be asserted while target temperature cannot be achieved after 3 minutes
+of full speed rotation of corresponding fan.
+
+In addition to the alarms described above, there is a CHAS alarm on the chips
+which triggers if your computer case is open (This one is latched, contrary
+to realtime alarms).
+
+The chips only update values each 3 seconds; reading them more often will
+do no harm, but will return 'old' values.
+
+
+W83792D PROBLEMS
+----------------
+Known problems:
+       - This driver is only for Winbond W83792D C version device, there
+         are also some motherboards with B version W83792D device. The
+         calculation method to in6-in7(measured value, limits) is a little
+         different between C and B version. C or B version can be identified
+         by CR[0x49h].
+       - The function of vid and vrm has not been finished, because I'm NOT
+         very familiar with them. Adding support is welcome.
+       - The function of chassis open detection needs more tests.
+       - If you have ASUS server board and chip was not found: Then you will
+         need to upgrade to latest (or beta) BIOS. If it does not help please
+         contact us.
+
+Fan control
+-----------
+
+Manual mode
+-----------
+
+Works as expected. You just need to specify desired PWM/DC value (fan speed)
+in appropriate pwm# file.
+
+Thermal cruise
+--------------
+
+In this mode, W83792D provides the Smart Fan system to automatically control
+fan speed to keep the temperatures of CPU and the system within specific
+range. At first a wanted temperature and interval must be set. This is done
+via thermal_cruise# file. The tolerance# file serves to create T +- tolerance
+interval. The fan speed will be lowered as long as the current temperature
+remains below the thermal_cruise# +- tolerance# value. Once the temperature
+exceeds the high limit (T+tolerance), the fan will be turned on with a
+specific speed set by pwm# and automatically controlled its PWM duty cycle
+with the temperature varying. Three conditions may occur:
+
+(1) If the temperature still exceeds the high limit, PWM duty
+cycle will increase slowly.
+
+(2) If the temperature goes below the high limit, but still above the low
+limit (T-tolerance), the fan speed will be fixed at the current speed because
+the temperature is in the target range.
+
+(3) If the temperature goes below the low limit, PWM duty cycle will decrease
+slowly to 0 or a preset stop value until the temperature exceeds the low
+limit. (The preset stop value handling is not yet implemented in driver)
+
+Smart Fan II
+------------
+
+W83792D also provides a special mode for fan. Four temperature points are
+available. When related temperature sensors detects the temperature in preset
+temperature region (sf2_point@_fan# +- tolerance#) it will cause fans to run
+on programmed value from sf2_level@_fan#. You need to set four temperatures
+for each fan.
+
+
+/sys files
+----------
+
+pwm[1-3] - this file stores PWM duty cycle or DC value (fan speed) in range:
+       0 (stop) to 255 (full)
+pwm[1-3]_enable - this file controls mode of fan/temperature control:
+            * 0 Disabled
+            * 1 Manual mode
+            * 2 Smart Fan II
+            * 3 Thermal Cruise
+pwm[1-3]_mode - Select PWM of DC mode
+            * 0 DC
+            * 1 PWM
+thermal_cruise[1-3] - Selects the desired temperature for cruise (degC)
+tolerance[1-3] - Value in degrees of Celsius (degC) for +- T
+sf2_point[1-4]_fan[1-3] - four temperature points for each fan for Smart Fan II
+sf2_level[1-3]_fan[1-3] - three PWM/DC levels for each fan for Smart Fan II
index b02002898a09cebd411dbed0c38ba7aeecb69919..96fec562a8e9020fc92a5d8c1de5676bda953cf8 100644 (file)
@@ -4,22 +4,13 @@ Kernel driver max6875
 Supported chips:
   * Maxim MAX6874, MAX6875
     Prefix: 'max6875'
-    Addresses scanned: 0x50, 0x52
+    Addresses scanned: None (see below)
     Datasheet:
         http://pdfserv.maxim-ic.com/en/ds/MAX6874-MAX6875.pdf
 
 Author: Ben Gardner <bgardner@wabtec.com>
 
 
-Module Parameters
------------------
-
-* allow_write int
-  Set to non-zero to enable write permission:
-  *0: Read only
-   1: Read and write
-
-
 Description
 -----------
 
@@ -33,34 +24,85 @@ registers.
 
 The Maxim MAX6874 is a similar, mostly compatible device, with more intputs
 and outputs:
-
              vin     gpi    vout
 MAX6874        6       4       8
 MAX6875        4       3       5
 
-MAX6874 chips can have four different addresses (as opposed to only two for
-the MAX6875). The additional addresses (0x54 and 0x56) are not probed by
-this driver by default, but the probe module parameter can be used if
-needed.
-
-See the datasheet for details on how to program the EEPROM.
+See the datasheet for more information.
 
 
 Sysfs entries
 -------------
 
-eeprom_user   - 512 bytes of user-defined EEPROM space. Only writable if
-                allow_write was set and register 0x43 is 0.
-
-eeprom_config - 70 bytes of config EEPROM. Note that changes will not get
-                loaded into register space until a power cycle or device reset.
-
-reg_config    - 70 bytes of register space. Any changes take affect immediately.
+eeprom        - 512 bytes of user-defined EEPROM space.
 
 
 General Remarks
 ---------------
 
-A typical application will require that the EEPROMs be programmed once and
-never altered afterwards.
+Valid addresses for the MAX6875 are 0x50 and 0x52.
+Valid addresses for the MAX6874 are 0x50, 0x52, 0x54 and 0x56.
+The driver does not probe any address, so you must force the address.
+
+Example:
+$ modprobe max6875 force=0,0x50
+
+The MAX6874/MAX6875 ignores address bit 0, so this driver attaches to multiple
+addresses.  For example, for address 0x50, it also reserves 0x51.
+The even-address instance is called 'max6875', the odd one is 'max6875 subclient'.
+
+
+Programming the chip using i2c-dev
+----------------------------------
+
+Use the i2c-dev interface to access and program the chips.
+Reads and writes are performed differently depending on the address range.
+
+The configuration registers are at addresses 0x00 - 0x45.
+Use i2c_smbus_write_byte_data() to write a register and
+i2c_smbus_read_byte_data() to read a register.
+The command is the register number.
+
+Examples:
+To write a 1 to register 0x45:
+  i2c_smbus_write_byte_data(fd, 0x45, 1);
+
+To read register 0x45:
+  value = i2c_smbus_read_byte_data(fd, 0x45);
+
+
+The configuration EEPROM is at addresses 0x8000 - 0x8045.
+The user EEPROM is at addresses 0x8100 - 0x82ff.
+
+Use i2c_smbus_write_word_data() to write a byte to EEPROM.
+
+The command is the upper byte of the address: 0x80, 0x81, or 0x82.
+The data word is the lower part of the address or'd with data << 8.
+  cmd = address >> 8;
+  val = (address & 0xff) | (data << 8);
+
+Example:
+To write 0x5a to address 0x8003:
+  i2c_smbus_write_word_data(fd, 0x80, 0x5a03);
+
+
+Reading data from the EEPROM is a little more complicated.
+Use i2c_smbus_write_byte_data() to set the read address and then
+i2c_smbus_read_byte() or i2c_smbus_read_i2c_block_data() to read the data.
+
+Example:
+To read data starting at offset 0x8100, first set the address:
+  i2c_smbus_write_byte_data(fd, 0x81, 0x00);
+
+And then read the data
+  value = i2c_smbus_read_byte(fd);
+
+  or
+
+  count = i2c_smbus_read_i2c_block_data(fd, 0x84, buffer);
+
+The block read should read 16 bytes.
+0x84 is the block read command.
+
+See the datasheet for more details.
 
index 8a78a95ae04e25d2aae7d05f6ef91068bccf307f..41ffefbdc60c488e339162454d16043591006f2c 100644 (file)
@@ -115,7 +115,7 @@ CHECKING THROUGH /DEV
 If you try to access an adapter from a userspace program, you will have
 to use the /dev interface. You will still have to check whether the
 functionality you need is supported, of course. This is done using
-the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2c_detect
+the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
 program, is below:
 
   int file;
index a7adbdd9ea8a51aa46298cd48bdd566b1f9566d3..4849dfd6961c7d2ed2d21eb5e7a65cf72cf0b755 100644 (file)
@@ -1,4 +1,4 @@
-Revision 4, 2004-03-30
+Revision 5, 2005-07-29
 Jean Delvare <khali@linux-fr.org>
 Greg KH <greg@kroah.com>
 
@@ -17,20 +17,22 @@ yours for best results.
 
 Technical changes:
 
-* [Includes] Get rid of "version.h". Replace <linux/i2c-proc.h> with
-  <linux/i2c-sensor.h>. Includes typically look like that:
+* [Includes] Get rid of "version.h" and <linux/i2c-proc.h>.
+  Includes typically look like that:
   #include <linux/module.h>
   #include <linux/init.h>
   #include <linux/slab.h>
   #include <linux/i2c.h>
-  #include <linux/i2c-sensor.h>
-  #include <linux/i2c-vid.h>   /* if you need VRM support */
+  #include <linux/hwmon.h>     /* for hardware monitoring drivers */
+  #include <linux/hwmon-sysfs.h>
+  #include <linux/hwmon-vid.h> /* if you need VRM support */
   #include <asm/io.h>          /* if you have I/O operations */
   Please respect this inclusion order. Some extra headers may be
   required for a given driver (e.g. "lm75.h").
 
-* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
-  becomes I2C_CLIENT_ISA_END.
+* [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, ISA addresses
+  are no more handled by the i2c core.
+  SENSORS_INSMOD_<n> becomes I2C_CLIENT_INSMOD_<n>.
 
 * [Client data] Get rid of sysctl_id. Try using standard names for
   register values (for example, temp_os becomes temp_max). You're
@@ -66,13 +68,15 @@ Technical changes:
   if (!(adapter->class & I2C_CLASS_HWMON))
           return 0;
   ISA-only drivers of course don't need this.
+  Call i2c_probe() instead of i2c_detect().
 
 * [Detect] As mentioned earlier, the flags parameter is gone.
   The type_name and client_name strings are replaced by a single
   name string, which will be filled with a lowercase, short string
   (typically the driver name, e.g. "lm75").
   In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
-  useless.
+  useless. Same for isa-only drivers, as the test would always be
+  true. Only hybrid drivers (which are quite rare) still need it.
   The errorN labels are reduced to the number needed. If that number
   is 2 (i2c-only drivers), it is advised that the labels are named
   exit and exit_free. For i2c+isa drivers, labels should be named
@@ -86,6 +90,8 @@ Technical changes:
   device_create_file. Move the driver initialization before any
   sysfs file creation.
   Drop client->id.
+  Drop any 24RF08 corruption prevention you find, as this is now done
+  at the i2c-core level, and doing it twice voids it.
 
 * [Init] Limits must not be set by the driver (can be done later in
   user-space). Chip should not be reset default (although a module
@@ -93,7 +99,8 @@ Technical changes:
   limited to the strictly necessary steps.
 
 * [Detach] Get rid of data, remove the call to
-  i2c_deregister_entry.
+  i2c_deregister_entry. Do not log an error message if
+  i2c_detach_client fails, as i2c-core will now do it for you.
 
 * [Update] Don't access client->data directly, use
   i2c_get_clientdata(client) instead.
index 91664be91ffcd692d62e3602fa8f1b3f9a27f381..077275722a7ccce46cfb1c12e04ed3abe688bd1b 100644 (file)
@@ -148,15 +148,15 @@ are defined in i2c.h to help you support them, as well as a generic
 detection algorithm.
 
 You do not have to use this parameter interface; but don't try to use
-function i2c_probe() (or i2c_detect()) if you don't.
+function i2c_probe() if you don't.
 
 NOTE: If you want to write a `sensors' driver, the interface is slightly
       different! See below.
 
 
 
-Probing classes (i2c)
----------------------
+Probing classes
+---------------
 
 All parameters are given as lists of unsigned 16-bit integers. Lists are
 terminated by I2C_CLIENT_END.
@@ -171,12 +171,18 @@ The following lists are used internally:
    ignore: insmod parameter.
      A list of pairs. The first value is a bus number (-1 for any I2C bus), 
      the second is the I2C address. These addresses are never probed. 
-     This parameter overrules 'normal' and 'probe', but not the 'force' lists.
+     This parameter overrules the 'normal_i2c' list only.
    force: insmod parameter. 
      A list of pairs. The first value is a bus number (-1 for any I2C bus),
      the second is the I2C address. A device is blindly assumed to be on
      the given address, no probing is done. 
 
+Additionally, kind-specific force lists may optionally be defined if
+the driver supports several chip kinds. They are grouped in a
+NULL-terminated list of pointers named forces, those first element if the
+generic force list mentioned above. Each additional list correspond to an
+insmod parameter of the form force_<kind>.
+
 Fortunately, as a module writer, you just have to define the `normal_i2c' 
 parameter. The complete declaration could look like this:
 
@@ -186,66 +192,17 @@ parameter. The complete declaration could look like this:
 
   /* Magic definition of all other variables and things */
   I2C_CLIENT_INSMOD;
+  /* Or, if your driver supports, say, 2 kind of devices: */
+  I2C_CLIENT_INSMOD_2(foo, bar);
+
+If you use the multi-kind form, an enum will be defined for you:
+  enum chips { any_chip, foo, bar, ... }
+You can then (and certainly should) use it in the driver code.
 
 Note that you *have* to call the defined variable `normal_i2c',
 without any prefix!
 
 
-Probing classes (sensors)
--------------------------
-
-If you write a `sensors' driver, you use a slightly different interface.
-As well as I2C addresses, we have to cope with ISA addresses. Also, we
-use a enum of chip types. Don't forget to include `sensors.h'.
-
-The following lists are used internally. They are all lists of integers.
-
-   normal_i2c: filled in by the module writer. Terminated by SENSORS_I2C_END.
-     A list of I2C addresses which should normally be examined.
-   normal_isa: filled in by the module writer. Terminated by SENSORS_ISA_END.
-     A list of ISA addresses which should normally be examined.
-   probe: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the address. These
-     addresses are also probed, as if they were in the 'normal' list.
-   ignore: insmod parameter. Initialize this list with SENSORS_I2C_END values.
-     A list of pairs. The first value is a bus number (SENSORS_ISA_BUS for
-     the ISA bus, -1 for any I2C bus), the second is the I2C address. These
-     addresses are never probed. This parameter overrules 'normal' and 
-     'probe', but not the 'force' lists.
-
-Also used is a list of pointers to sensors_force_data structures:
-   force_data: insmod parameters. A list, ending with an element of which
-     the force field is NULL.
-     Each element contains the type of chip and a list of pairs.
-     The first value is a bus number (SENSORS_ISA_BUS for the ISA bus, 
-     -1 for any I2C bus), the second is the address. 
-     These are automatically translated to insmod variables of the form
-     force_foo.
-
-So we have a generic insmod variabled `force', and chip-specific variables
-`force_CHIPNAME'.
-
-Fortunately, as a module writer, you just have to define the `normal_i2c' 
-and `normal_isa' parameters, and define what chip names are used. 
-The complete declaration could look like this:
-  /* Scan i2c addresses 0x37, and 0x48 to 0x4f */
-  static unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4b, 0x4c,
-                                         0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-  /* Scan ISA address 0x290 */
-  static unsigned int normal_isa[] = {0x0290,SENSORS_ISA_END};
-
-  /* Define chips foo and bar, as well as all module parameters and things */
-  SENSORS_INSMOD_2(foo,bar);
-
-If you have one chip, you use macro SENSORS_INSMOD_1(chip), if you have 2
-you use macro SENSORS_INSMOD_2(chip1,chip2), etc. If you do not want to
-bother with chip types, you can use SENSORS_INSMOD_0.
-
-A enum is automatically defined as follows:
-  enum chips { any_chip, chip1, chip2, ... }
-
-
 Attaching to an adapter
 -----------------------
 
@@ -264,17 +221,10 @@ detected at a specific address, another callback is called.
     return i2c_probe(adapter,&addr_data,&foo_detect_client);
   }
 
-For `sensors' drivers, use the i2c_detect function instead:
-  
-  int foo_attach_adapter(struct i2c_adapter *adapter)
-  { 
-    return i2c_detect(adapter,&addr_data,&foo_detect_client);
-  }
-
 Remember, structure `addr_data' is defined by the macros explained above,
 so you do not have to define it yourself.
 
-The i2c_probe or i2c_detect function will call the foo_detect_client
+The i2c_probe function will call the foo_detect_client
 function only for those i2c addresses that actually have a device on
 them (unless a `force' parameter was used). In addition, addresses that
 are already in use (by some other registered client) are skipped.
@@ -283,19 +233,18 @@ are already in use (by some other registered client) are skipped.
 The detect client function
 --------------------------
 
-The detect client function is called by i2c_probe or i2c_detect.
-The `kind' parameter contains 0 if this call is due to a `force'
-parameter, and -1 otherwise (for i2c_detect, it contains 0 if
-this call is due to the generic `force' parameter, and the chip type
-number if it is due to a specific `force' parameter).
+The detect client function is called by i2c_probe. The `kind' parameter
+contains -1 for a probed detection, 0 for a forced detection, or a positive
+number for a forced detection with a chip type forced.
 
 Below, some things are only needed if this is a `sensors' driver. Those
 parts are between /* SENSORS ONLY START */ and /* SENSORS ONLY END */
 markers. 
 
-This function should only return an error (any value != 0) if there is
-some reason why no more detection should be done anymore. If the
-detection just fails for this address, return 0.
+Returning an error different from -ENODEV in a detect function will cause
+the detection to stop: other addresses and adapters won't be scanned.
+This should only be done on fatal or internal errors, such as a memory
+shortage or i2c_attach_client failing.
 
 For now, you can ignore the `flags' parameter. It is there for future use.
 
@@ -320,11 +269,10 @@ For now, you can ignore the `flags' parameter. It is there for future use.
     const char *type_name = "";
     int is_isa = i2c_is_isa_adapter(adapter);
 
-    if (is_isa) {
+    /* Do this only if the chip can additionally be found on the ISA bus
+       (hybrid chip). */
 
-      /* If this client can't be on the ISA bus at all, we can stop now
-         (call `goto ERROR0'). But for kicks, we will assume it is all
-         right. */
+    if (is_isa) {
 
       /* Discard immediately if this ISA range is already used */
       if (check_region(address,FOO_EXTENT))
@@ -495,15 +443,13 @@ much simpler than the attachment code, fortunately!
     /* SENSORS ONLY END */
 
     /* Try to detach the client from i2c space */
-    if ((err = i2c_detach_client(client))) {
-      printk("foo.o: Client deregistration failed, client not detached.\n");
+    if ((err = i2c_detach_client(client)))
       return err;
-    }
 
-    /* SENSORS ONLY START */
+    /* HYBRID SENSORS CHIP ONLY START */
     if i2c_is_isa_client(client)
       release_region(client->addr,LM78_EXTENT);
-    /* SENSORS ONLY END */
+    /* HYBRID SENSORS CHIP ONLY END */
 
     kfree(client); /* Frees client data too, if allocated at the same time */
     return 0;
index 5899ec1504f3317c77f48805bd4d3cc8ab29cd8c..7e1f67130a16d595d2a7f5879dce0469993de085 100644 (file)
@@ -933,6 +933,13 @@ M: khc@pm.waw.pl
 W:     http://www.kernel.org/pub/linux/utils/net/hdlc/
 S:     Maintained
 
+HARDWARE MONITORING
+P:     Jean Delvare
+M:     khali@linux-fr.org
+L:     lm-sensors@lm-sensors.org
+W:     http://www.lm-sensors.nu/
+S:     Maintained
+
 HARMONY SOUND DRIVER
 P:     Kyle McMartin
 M:     kyle@parisc-linux.org
@@ -1014,7 +1021,7 @@ P:        William Irwin
 M:     wli@holomorphy.com
 S:     Maintained
 
-I2C AND SENSORS DRIVERS
+I2C SUBSYSTEM
 P:     Greg Kroah-Hartman
 M:     greg@kroah.com
 P:     Jean Delvare
index 140d5f851a5b0c735dffc620778f4735048152b9..138dc50270e3e51e714893602c937b5fa95ec14e 100644 (file)
@@ -12,12 +12,20 @@ config HWMON
          of a system. Most modern motherboards include such a device. It
          can include temperature sensors, voltage sensors, fan speed
          sensors and various additional features such as the ability to
-         control the speed of the fans.
+         control the speed of the fans.  If you want this support you
+         should say Y here and also to the specific driver(s) for your
+         sensors chip(s) below.
+
+         This support can also be built as a module.  If so, the module
+         will be called hwmon.
+
+config HWMON_VID
+       tristate
+       default n
 
 config SENSORS_ADM1021
        tristate "Analog Devices ADM1021 and compatibles"
        depends on HWMON && I2C
-       select I2C_SENSOR
        help
          If you say yes here you get support for Analog Devices ADM1021
          and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
@@ -30,7 +38,7 @@ config SENSORS_ADM1021
 config SENSORS_ADM1025
        tristate "Analog Devices ADM1025 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM1025
          and Philips NE1619 sensor chips.
@@ -41,7 +49,7 @@ config SENSORS_ADM1025
 config SENSORS_ADM1026
        tristate "Analog Devices ADM1026 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM1026
          sensor chip.
@@ -52,7 +60,6 @@ config SENSORS_ADM1026
 config SENSORS_ADM1031
        tristate "Analog Devices ADM1031 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for Analog Devices ADM1031
          and ADM1030 sensor chips.
@@ -63,7 +70,7 @@ config SENSORS_ADM1031
 config SENSORS_ADM9240
        tristate "Analog Devices ADM9240 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for Analog Devices ADM9240,
          Dallas DS1780, National Semiconductor LM81 sensor chips.
@@ -74,7 +81,7 @@ config SENSORS_ADM9240
 config SENSORS_ASB100
        tristate "Asus ASB100 Bach"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for the ASB100 Bach sensor
          chip found on some Asus mainboards.
@@ -85,7 +92,7 @@ config SENSORS_ASB100
 config SENSORS_ATXP1
        tristate "Attansic ATXP1 VID controller"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for the Attansic ATXP1 VID
          controller.
@@ -99,7 +106,6 @@ config SENSORS_ATXP1
 config SENSORS_DS1621
        tristate "Dallas Semiconductor DS1621 and DS1625"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for Dallas Semiconductor
          DS1621 and DS1625 sensor chips.
@@ -110,7 +116,6 @@ config SENSORS_DS1621
 config SENSORS_FSCHER
        tristate "FSC Hermes"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for Fujitsu Siemens
          Computers Hermes sensor chips.
@@ -121,7 +126,6 @@ config SENSORS_FSCHER
 config SENSORS_FSCPOS
        tristate "FSC Poseidon"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for Fujitsu Siemens
          Computers Poseidon sensor chips.
@@ -132,7 +136,6 @@ config SENSORS_FSCPOS
 config SENSORS_GL518SM
        tristate "Genesys Logic GL518SM"
        depends on HWMON && I2C
-       select I2C_SENSOR
        help
          If you say yes here you get support for Genesys Logic GL518SM
          sensor chips.
@@ -143,7 +146,7 @@ config SENSORS_GL518SM
 config SENSORS_GL520SM
        tristate "Genesys Logic GL520SM"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for Genesys Logic GL520SM
          sensor chips.
@@ -154,7 +157,8 @@ config SENSORS_GL520SM
 config SENSORS_IT87
        tristate "ITE IT87xx and compatibles"
        depends on HWMON && I2C
-       select I2C_SENSOR
+       select I2C_ISA
+       select HWMON_VID
        help
          If you say yes here you get support for ITE IT87xx sensor chips
          and clones: SiS960.
@@ -165,7 +169,6 @@ config SENSORS_IT87
 config SENSORS_LM63
        tristate "National Semiconductor LM63"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for the National Semiconductor
          LM63 remote diode digital temperature sensor with integrated fan
@@ -178,7 +181,6 @@ config SENSORS_LM63
 config SENSORS_LM75
        tristate "National Semiconductor LM75 and compatibles"
        depends on HWMON && I2C
-       select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM75
          sensor chips and clones: Dallas Semiconductor DS75 and DS1775 (in
@@ -194,7 +196,6 @@ config SENSORS_LM75
 config SENSORS_LM77
        tristate "National Semiconductor LM77"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM77
          sensor chips.
@@ -205,7 +206,8 @@ config SENSORS_LM77
 config SENSORS_LM78
        tristate "National Semiconductor LM78 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select I2C_ISA
+       select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM78,
          LM78-J and LM79.
@@ -216,7 +218,6 @@ config SENSORS_LM78
 config SENSORS_LM80
        tristate "National Semiconductor LM80"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor
          LM80 sensor chips.
@@ -227,7 +228,6 @@ config SENSORS_LM80
 config SENSORS_LM83
        tristate "National Semiconductor LM83"
        depends on HWMON && I2C
-       select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor
          LM83 sensor chips.
@@ -238,7 +238,7 @@ config SENSORS_LM83
 config SENSORS_LM85
        tristate "National Semiconductor LM85 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM85
          sensor chips and clones: ADT7463, EMC6D100, EMC6D102 and ADM1027.
@@ -249,7 +249,7 @@ config SENSORS_LM85
 config SENSORS_LM87
        tristate "National Semiconductor LM87"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
+       select HWMON_VID
        help
          If you say yes here you get support for National Semiconductor LM87
          sensor chips.
@@ -260,7 +260,6 @@ config SENSORS_LM87
 config SENSORS_LM90
        tristate "National Semiconductor LM90 and compatibles"
        depends on HWMON && I2C
-       select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM90,
          LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
@@ -275,7 +274,6 @@ config SENSORS_LM90
 config SENSORS_LM92
        tristate "National Semiconductor LM92 and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for National Semiconductor LM92
          and Maxim MAX6635 sensor chips.
@@ -286,7 +284,6 @@ config SENSORS_LM92
 config SENSORS_MAX1619
        tristate "Maxim MAX1619 sensor chip"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for MAX1619 sensor chip.
 
@@ -296,8 +293,8 @@ config SENSORS_MAX1619
 config SENSORS_PC87360
        tristate "National Semiconductor PC87360 family"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        select I2C_ISA
+       select HWMON_VID
        help
          If you say yes here you get access to the hardware monitoring
          functions of the National Semiconductor PC8736x Super-I/O chips.
@@ -311,7 +308,6 @@ config SENSORS_PC87360
 config SENSORS_SIS5595
        tristate "Silicon Integrated Systems Corp. SiS5595"
        depends on HWMON && I2C && PCI && EXPERIMENTAL
-       select I2C_SENSOR
        select I2C_ISA
        help
          If you say yes here you get support for the integrated sensors in
@@ -323,7 +319,6 @@ config SENSORS_SIS5595
 config SENSORS_SMSC47M1
        tristate "SMSC LPC47M10x and compatibles"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        select I2C_ISA
        help
          If you say yes here you get support for the integrated fan
@@ -336,7 +331,6 @@ config SENSORS_SMSC47M1
 config SENSORS_SMSC47B397
        tristate "SMSC LPC47B397-NC"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        select I2C_ISA
        help
          If you say yes here you get support for the SMSC LPC47B397-NC
@@ -348,7 +342,6 @@ config SENSORS_SMSC47B397
 config SENSORS_VIA686A
        tristate "VIA686A"
        depends on HWMON && I2C && PCI
-       select I2C_SENSOR
        select I2C_ISA
        help
          If you say yes here you get support for the integrated sensors in
@@ -360,7 +353,8 @@ config SENSORS_VIA686A
 config SENSORS_W83781D
        tristate "Winbond W83781D, W83782D, W83783S, W83627HF, Asus AS99127F"
        depends on HWMON && I2C
-       select I2C_SENSOR
+       select I2C_ISA
+       select HWMON_VID
        help
          If you say yes here you get support for the Winbond W8378x series
          of sensor chips: the W83781D, W83782D, W83783S and W83627HF,
@@ -369,10 +363,18 @@ config SENSORS_W83781D
          This driver can also be built as a module.  If so, the module
          will be called w83781d.
 
+config SENSORS_W83792D
+       tristate "Winbond W83792D"
+       depends on HWMON && I2C && EXPERIMENTAL
+       help
+         If you say yes here you get support for the Winbond W83792D chip.
+
+         This driver can also be built as a module.  If so, the module
+         will be called w83792d.
+
 config SENSORS_W83L785TS
        tristate "Winbond W83L785TS-S"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        help
          If you say yes here you get support for the Winbond W83L785TS-S
          sensor chip, which is used on the Asus A7N8X, among other
@@ -384,8 +386,8 @@ config SENSORS_W83L785TS
 config SENSORS_W83627HF
        tristate "Winbond W83627HF, W83627THF, W83637HF, W83697HF"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        select I2C_ISA
+       select HWMON_VID
        help
          If you say yes here you get support for the Winbond W836X7 series
          of sensor chips: the W83627HF, W83627THF, W83637HF, and the W83697HF
@@ -396,7 +398,6 @@ config SENSORS_W83627HF
 config SENSORS_W83627EHF
        tristate "Winbond W83627EHF"
        depends on HWMON && I2C && EXPERIMENTAL
-       select I2C_SENSOR
        select I2C_ISA
        help
          If you say yes here you get preliminary support for the hardware
@@ -404,6 +405,9 @@ config SENSORS_W83627EHF
          Only fan and temperature inputs are supported at the moment, while
          the chip does much more than that.
 
+         This driver also supports the W83627EHG, which is the lead-free
+         version of the W83627EHF.
+
          This driver can also be built as a module.  If so, the module
          will be called w83627ehf.
 
index 2781403a0236d1e02d3c82d3bdaac323da2a2dd7..381f1bf04cc5531f2f4f2376f2c0afc61fff57b7 100644 (file)
@@ -2,9 +2,13 @@
 # Makefile for sensor chip drivers.
 #
 
+obj-$(CONFIG_HWMON)            += hwmon.o
+obj-$(CONFIG_HWMON_VID)                += hwmon-vid.o
+
 # asb100, then w83781d go first, as they can override other drivers' addresses.
 obj-$(CONFIG_SENSORS_ASB100)   += asb100.o
 obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o
+obj-$(CONFIG_SENSORS_W83792D)  += w83792d.o
 obj-$(CONFIG_SENSORS_W83781D)  += w83781d.o
 
 obj-$(CONFIG_SENSORS_ADM1021)  += adm1021.o
index d2c774c32f45b942a92453eb110346fa028e7bd7..e928cdb041cba28d76f23821172becc7c3589397 100644 (file)
@@ -24,7 +24,8 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 
 /* Addresses to scan */
@@ -32,10 +33,9 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
                                        0x29, 0x2a, 0x2b,
                                        0x4c, 0x4d, 0x4e, 
                                        I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
+I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
 
 /* adm1021 constants specified below */
 
@@ -89,6 +89,7 @@ clearing it.  Weird, ey?   --Phil  */
 /* Each client has this additional data */
 struct adm1021_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        enum chips type;
 
        struct semaphore update_lock;
@@ -185,7 +186,7 @@ static int adm1021_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, adm1021_detect);
+       return i2c_probe(adapter, &addr_data, adm1021_detect);
 }
 
 static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -196,15 +197,6 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
        int err = 0;
        const char *type_name = "";
 
-       /* Make sure we aren't probing the ISA bus!! This is just a safety check
-          at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
-       if (i2c_is_isa_adapter(adapter)) {
-               dev_dbg(&adapter->dev, "adm1021_detect called for an ISA bus adapter?!?\n");
-               return 0;
-       }
-#endif
-
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
                goto error0;
 
@@ -295,6 +287,12 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
                adm1021_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto error2;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_temp1_max);
        device_create_file(&new_client->dev, &dev_attr_temp1_min);
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
@@ -305,6 +303,8 @@ static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+error2:
+       i2c_detach_client(new_client);
 error1:
        kfree(data);
 error0:
@@ -322,14 +322,15 @@ static void adm1021_init_client(struct i2c_client *client)
 
 static int adm1021_detach_client(struct i2c_client *client)
 {
+       struct adm1021_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index e452d0daf906e314f9b0a2444aa64a9b93803609..526b7ff179ebb83c0bc1197a978e85344424a6c8 100644 (file)
@@ -50,8 +50,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_2(adm1025, ne1619);
+I2C_CLIENT_INSMOD_2(adm1025, ne1619);
 
 /*
  * The ADM1025 registers
@@ -132,6 +132,7 @@ static struct i2c_driver adm1025_driver = {
 
 struct adm1025_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -312,7 +313,7 @@ static int adm1025_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, adm1025_detect);
+       return i2c_probe(adapter, &addr_data, adm1025_detect);
 }
 
 /*
@@ -416,6 +417,12 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
        adm1025_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in1_input);
        device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -452,6 +459,8 @@ static int adm1025_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -464,7 +473,7 @@ static void adm1025_init_client(struct i2c_client *client)
        struct adm1025_data *data = i2c_get_clientdata(client);
        int i;
 
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        /*
         * Set high limits
@@ -502,15 +511,15 @@ static void adm1025_init_client(struct i2c_client *client)
 
 static int adm1025_detach_client(struct i2c_client *client)
 {
+       struct adm1025_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index c8a7f47911f99f315189cc60cb73ba23e888b5fb..625158110fd4ff74294debbc2a67a550012f90c9 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(adm1026);
+I2C_CLIENT_INSMOD_1(adm1026);
 
 static int gpio_input[17]  = { -1, -1, -1, -1, -1, -1, -1, -1, -1,
                                -1, -1, -1, -1, -1, -1, -1, -1 }; 
@@ -259,6 +259,7 @@ struct pwm_data {
 
 struct adm1026_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -319,13 +320,15 @@ int adm1026_attach_adapter(struct i2c_adapter *adapter)
        if (!(adapter->class & I2C_CLASS_HWMON)) {
                return 0;
        }
-       return i2c_detect(adapter, &addr_data, adm1026_detect);
+       return i2c_probe(adapter, &addr_data, adm1026_detect);
 }
 
 int adm1026_detach_client(struct i2c_client *client)
 {
+       struct adm1026_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->class_dev);
        i2c_detach_client(client);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
@@ -1549,12 +1552,18 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
                goto exitfree;
 
        /* Set the VRM version */
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        /* Initialize the ADM1026 chip */
        adm1026_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exitdetach;
+       }
+
        device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
        device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
        device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
@@ -1690,6 +1699,8 @@ int adm1026_detect(struct i2c_adapter *adapter, int address,
        return 0;
 
        /* Error out and cleanup code */
+exitdetach:
+       i2c_detach_client(new_client);
 exitfree:
        kfree(data);
 exit:
index 9362509572709596d92849a666199f4cf1bcb46a..58338ed7c8a1c676095e3c9672fa08e453455a7b 100644 (file)
@@ -26,7 +26,8 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Following macros takes channel parameter starting from 0 to 2 */
 #define ADM1031_REG_FAN_SPEED(nr)      (0x08 + (nr))
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(adm1030, adm1031);
+I2C_CLIENT_INSMOD_2(adm1030, adm1031);
 
 typedef u8 auto_chan_table_t[8][2];
 
 /* Each client has this additional data */
 struct adm1031_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        int chip_type;
        char valid;             /* !=0 if following fields are valid */
@@ -725,10 +726,10 @@ static int adm1031_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, adm1031_detect);
+       return i2c_probe(adapter, &addr_data, adm1031_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        struct i2c_client *new_client;
@@ -788,6 +789,12 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
        adm1031_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_fan1_input);
        device_create_file(&new_client->dev, &dev_attr_fan1_div);
        device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -833,6 +840,8 @@ static int adm1031_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -841,11 +850,14 @@ exit:
 
 static int adm1031_detach_client(struct i2c_client *client)
 {
+       struct adm1031_data *data = i2c_get_clientdata(client);
        int ret;
+
+       hwmon_device_unregister(data->class_dev);
        if ((ret = i2c_detach_client(client)) != 0) {
                return ret;
        }
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index ce2a6eb93f6e5d4c7baed6fc26797b86988559e4..bc7faef162f7b562fc99a8c8481d73c0809e6e2c 100644 (file)
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f,
                                        I2C_CLIENT_END };
 
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
 /* Insmod parameters */
-SENSORS_INSMOD_3(adm9240, ds1780, lm81);
+I2C_CLIENT_INSMOD_3(adm9240, ds1780, lm81);
 
 /* ADM9240 registers */
 #define ADM9240_REG_MAN_ID             0x3e
@@ -150,6 +149,7 @@ static struct i2c_driver adm9240_driver = {
 struct adm9240_data {
        enum chips type;
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid;
        unsigned long last_updated_measure;
@@ -582,6 +582,12 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
        adm9240_init_client(new_client);
 
        /* populate sysfs filesystem */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in0_min);
        device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -615,6 +621,9 @@ static int adm9240_detect(struct i2c_adapter *adapter, int address, int kind)
        device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
 
        return 0;
+
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -625,20 +634,20 @@ static int adm9240_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, adm9240_detect);
+       return i2c_probe(adapter, &addr_data, adm9240_detect);
 }
 
 static int adm9240_detach_client(struct i2c_client *client)
 {
+       struct adm9240_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                               "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
@@ -648,7 +657,7 @@ static void adm9240_init_client(struct i2c_client *client)
        u8 conf = adm9240_read_value(client, ADM9240_REG_CONFIG);
        u8 mode = adm9240_read_value(client, ADM9240_REG_TEMP_CONF) & 3;
 
-       data->vrm = i2c_which_vrm(); /* need this to report vid as mV */
+       data->vrm = vid_which_vrm(); /* need this to report vid as mV */
 
        dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10,
                        data->vrm % 10);
index 70d996d6fe0a95c607c06afe6b0a8da01025a39e..8e34855a627406200510db53dd9e374d87ce7db9 100644 (file)
@@ -39,8 +39,9 @@
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include "lm75.h"
 /* I2C addresses to scan */
 static unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END };
 
-/* ISA addresses to scan (none) */
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
-
 /* Insmod parameters */
-SENSORS_INSMOD_1(asb100);
+I2C_CLIENT_INSMOD_1(asb100);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
        "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -183,6 +181,7 @@ static u8 DIV_TO_REG(long val)
    dynamically allocated, at the same time the client itself is allocated. */
 struct asb100_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -621,7 +620,7 @@ static int asb100_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, asb100_detect);
+       return i2c_probe(adapter, &addr_data, asb100_detect);
 }
 
 static int asb100_detect_subclients(struct i2c_adapter *adapter, int address,
@@ -714,14 +713,6 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
        struct i2c_client *new_client;
        struct asb100_data *data;
 
-       /* asb100 is SMBus only */
-       if (i2c_is_isa_adapter(adapter)) {
-               pr_debug("asb100.o: detect failed, "
-                               "cannot attach to legacy adapter!\n");
-               err = -ENODEV;
-               goto ERROR0;
-       }
-
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
                pr_debug("asb100.o: detect failed, "
                                "smbus byte data not supported!\n");
@@ -821,6 +812,12 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
        data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        device_create_file_in(new_client, 0);
        device_create_file_in(new_client, 1);
        device_create_file_in(new_client, 2);
@@ -847,6 +844,11 @@ static int asb100_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+ERROR3:
+       i2c_detach_client(data->lm75[1]);
+       i2c_detach_client(data->lm75[0]);
+       kfree(data->lm75[1]);
+       kfree(data->lm75[0]);
 ERROR2:
        i2c_detach_client(new_client);
 ERROR1:
@@ -857,21 +859,23 @@ ERROR0:
 
 static int asb100_detach_client(struct i2c_client *client)
 {
+       struct asb100_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "client deregistration failed; "
-                       "client not detached.\n");
+       /* main client */
+       if (data)
+               hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       if (i2c_get_clientdata(client)==NULL) {
-               /* subclients */
+       /* main client */
+       if (data)
+               kfree(data);
+
+       /* subclient */
+       else
                kfree(client);
-       } else {
-               /* main client */
-               kfree(i2c_get_clientdata(client));
-       }
 
        return 0;
 }
@@ -969,7 +973,7 @@ static void asb100_init_client(struct i2c_client *client)
 
        vid = asb100_read_value(client, ASB100_REG_VID_FANDIV) & 0x0f;
        vid |= (asb100_read_value(client, ASB100_REG_CHIPID) & 0x01) << 4;
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
        vid = vid_from_reg(vid, data->vrm);
 
        /* Start monitoring */
index fca3fc1cef72f02c1217d32cbfc0fa8876c63e40..deb4d34c9539bab6428d9f5fad5d62a357b787b2 100644 (file)
@@ -23,8 +23,9 @@
 #include <linux/module.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("System voltages control via Attansic ATXP1");
@@ -40,9 +41,8 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>");
 #define ATXP1_GPIO1MASK        0x0f
 
 static unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
-SENSORS_INSMOD_1(atxp1);
+I2C_CLIENT_INSMOD_1(atxp1);
 
 static int atxp1_attach_adapter(struct i2c_adapter * adapter);
 static int atxp1_detach_client(struct i2c_client * client);
@@ -59,6 +59,7 @@ static struct i2c_driver atxp1_driver = {
 
 struct atxp1_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        unsigned long last_updated;
        u8 valid;
@@ -252,7 +253,7 @@ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2);
 
 static int atxp1_attach_adapter(struct i2c_adapter *adapter)
 {
-       return i2c_detect(adapter, &addr_data, &atxp1_detect);
+       return i2c_probe(adapter, &addr_data, &atxp1_detect);
 };
 
 static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -295,7 +296,7 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Get VRM */
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        if ((data->vrm != 90) && (data->vrm != 91)) {
                dev_err(&new_client->dev, "Not supporting VRM %d.%d\n",
@@ -317,6 +318,12 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit_free;
        }
 
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_gpio1);
        device_create_file(&new_client->dev, &dev_attr_gpio2);
        device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
@@ -326,6 +333,8 @@ static int atxp1_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -334,14 +343,17 @@ exit:
 
 static int atxp1_detach_client(struct i2c_client * client)
 {
+       struct atxp1_data * data = i2c_get_clientdata(client);
        int err;
 
+       hwmon_device_unregister(data->class_dev);
+
        err = i2c_detach_client(client);
 
        if (err)
                dev_err(&client->dev, "Failed to detach client.\n");
        else
-               kfree(i2c_get_clientdata(client));
+               kfree(data);
 
        return err;
 };
index 5360d58804f6244e4de94a2b85b9b312cd36a409..b0199e063d0ebf02f1b8f92910086b0353f5cd55 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include "lm75.h"
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
                                        0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(ds1621);
+I2C_CLIENT_INSMOD_1(ds1621);
 static int polarity = -1;
 module_param(polarity, int, 0);
 MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low");
@@ -71,6 +71,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
 /* Each client has this additional data */
 struct ds1621_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid;                     /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
@@ -179,10 +180,10 @@ static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
 
 static int ds1621_attach_adapter(struct i2c_adapter *adapter)
 {
-       return i2c_detect(adapter, &addr_data, ds1621_detect);
+       return i2c_probe(adapter, &addr_data, ds1621_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int ds1621_detect(struct i2c_adapter *adapter, int address,
                   int kind)
 {
@@ -250,6 +251,12 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
        ds1621_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_alarms);
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
        device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -259,6 +266,8 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
 
 /* OK, this is not exactly good programming practice, usually. But it is
    very code-efficient in this case. */
+      exit_detach:
+       i2c_detach_client(new_client);
       exit_free:
        kfree(data);
       exit:
@@ -267,15 +276,15 @@ int ds1621_detect(struct i2c_adapter *adapter, int address,
 
 static int ds1621_detach_client(struct i2c_client *client)
 {
+       struct ds1621_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
index da411741c2c579964e8b1ac857d370154a8a33f3..eef6061d786b4e3c397b6bf9445a2d835be2b427 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 
 static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(fscher);
+I2C_CLIENT_INSMOD_1(fscher);
 
 /*
  * The FSCHER registers
@@ -132,6 +132,7 @@ static struct i2c_driver fscher_driver = {
 
 struct fscher_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -287,7 +288,7 @@ static int fscher_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, fscher_detect);
+       return i2c_probe(adapter, &addr_data, fscher_detect);
 }
 
 static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -341,6 +342,12 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
        fscher_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file_revision(new_client);
        device_create_file_alarms(new_client);
        device_create_file_control(new_client);
@@ -360,6 +367,8 @@ static int fscher_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -368,15 +377,15 @@ exit:
 
 static int fscher_detach_client(struct i2c_client *client)
 {
+       struct fscher_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 301ae98bd0adb1fca9d0f0e6687a538019439a0b..5fc77a5fed07b4b25d8fc21d27e22cc55a6a71a9 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/init.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 static unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
-SENSORS_INSMOD_1(fscpos);
+I2C_CLIENT_INSMOD_1(fscpos);
 
 /*
  * The FSCPOS registers
@@ -113,6 +113,7 @@ static struct i2c_driver fscpos_driver = {
  */
 struct fscpos_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid;             /* 0 until following fields are valid */
        unsigned long last_updated;     /* In jiffies */
@@ -434,7 +435,7 @@ static int fscpos_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, fscpos_detect);
+       return i2c_probe(adapter, &addr_data, fscpos_detect);
 }
 
 int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -496,6 +497,12 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
        dev_info(&new_client->dev, "Found fscpos chip, rev %u\n", data->revision);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_event);
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -526,6 +533,8 @@ int fscpos_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -534,14 +543,14 @@ exit:
 
 static int fscpos_detach_client(struct i2c_client *client)
 {
+       struct fscpos_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, client"
-                                                       " not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 6bedf729dcf5c251b27c18676af66fab4b68793f..256b9323c84b1e83f087cf51a3b34bb9190548fb 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(gl518sm_r00, gl518sm_r80);
+I2C_CLIENT_INSMOD_2(gl518sm_r00, gl518sm_r80);
 
 /* Many GL518 constants specified below */
 
@@ -117,6 +117,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 /* Each client has this additional data */
 struct gl518_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        enum chips type;
 
        struct semaphore update_lock;
@@ -346,7 +347,7 @@ static int gl518_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, gl518_detect);
+       return i2c_probe(adapter, &addr_data, gl518_detect);
 }
 
 static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -419,6 +420,12 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
        gl518_init_client((struct i2c_client *) new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in1_input);
        device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -450,6 +457,8 @@ static int gl518_detect(struct i2c_adapter *adapter, int address, int kind)
 /* OK, this is not exactly good programming practice, usually. But it is
    very code-efficient in this case. */
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -477,16 +486,15 @@ static void gl518_init_client(struct i2c_client *client)
 
 static int gl518_detach_client(struct i2c_client *client)
 {
+       struct gl518_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
-               return err;
-       }
+       hwmon_device_unregister(data->class_dev);
 
-       kfree(i2c_get_clientdata(client));
+       if ((err = i2c_detach_client(client)))
+               return err;
 
+       kfree(data);
        return 0;
 }
 
index 80ae8d30c2afc4d556f054a0f6e7fbcf1a0d627e..12fd757066fc9cad503b32a5c1df1e056909fbb5 100644 (file)
@@ -26,8 +26,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Type of the extra sensor */
 static unsigned short extra_sensor_type;
@@ -36,10 +37,9 @@ MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=tempe
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(gl520sm);
+I2C_CLIENT_INSMOD_1(gl520sm);
 
 /* Many GL520 constants specified below 
 One of the inputs can be configured as either temp or voltage.
@@ -120,6 +120,7 @@ static struct i2c_driver gl520_driver = {
 /* Client data */
 struct gl520_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid;             /* zero until the following fields are valid */
        unsigned long last_updated;     /* in jiffies */
@@ -518,7 +519,7 @@ static int gl520_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, gl520_detect);
+       return i2c_probe(adapter, &addr_data, gl520_detect);
 }
 
 static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -571,6 +572,12 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
        gl520_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file_vid(new_client, 0);
 
        device_create_file_in(new_client, 0);
@@ -592,6 +599,8 @@ static int gl520_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -608,7 +617,7 @@ static void gl520_init_client(struct i2c_client *client)
        conf = oldconf = gl520_read_value(client, GL520_REG_CONF);
 
        data->alarm_mask = 0xff;
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        if (extra_sensor_type == 1)
                conf &= ~0x10;
@@ -639,15 +648,15 @@ static void gl520_init_client(struct i2c_client *client)
 
 static int gl520_detach_client(struct i2c_client *client)
 {
+       struct gl520_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
diff --git a/drivers/hwmon/hwmon-vid.c b/drivers/hwmon/hwmon-vid.c
new file mode 100644 (file)
index 0000000..312769a
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+    hwmon-vid.c - VID/VRM/VRD voltage conversions
+
+    Copyright (c) 2004 Rudolf Marek <r.marek@sh.cvut.cz>
+
+    Partly imported from i2c-vid.h of the lm_sensors project
+    Copyright (c) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
+    With assistance from Trent Piepho <xyzzy@speakeasy.org>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/hwmon-vid.h>
+
+/*
+    Common code for decoding VID pins.
+
+    References:
+
+    For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines",
+    available at http://developer.intel.com/.
+
+    For VRD 10.0 and up, "VRD x.y Design Guide",
+    available at http://developer.intel.com/.
+
+    AMD Opteron processors don't follow the Intel specifications.
+    I'm going to "make up" 2.4 as the spec number for the Opterons.
+    No good reason just a mnemonic for the 24x Opteron processor
+    series.
+
+    Opteron VID encoding is:
+       00000  =  1.550 V
+       00001  =  1.525 V
+        . . . .
+       11110  =  0.800 V
+       11111  =  0.000 V (off)
+*/
+
+/* vrm is the VRM/VRD document version multiplied by 10.
+   val is the 4-, 5- or 6-bit VID code.
+   Returned value is in mV to avoid floating point in the kernel. */
+int vid_from_reg(int val, int vrm)
+{
+       int vid;
+
+       switch(vrm) {
+
+       case  0:
+               return 0;
+
+       case 100:               /* VRD 10.0 */
+               if((val & 0x1f) == 0x1f)
+                       return 0;
+               if((val & 0x1f) <= 0x09 || val == 0x0a)
+                       vid = 10875 - (val & 0x1f) * 250;
+               else
+                       vid = 18625 - (val & 0x1f) * 250;
+               if(val & 0x20)
+                       vid -= 125;
+               vid /= 10;      /* only return 3 dec. places for now */
+               return vid;
+
+       case 24:                /* Opteron processor */
+               return(val == 0x1f ? 0 : 1550 - val * 25);
+
+       case 91:                /* VRM 9.1 */
+       case 90:                /* VRM 9.0 */
+               return(val == 0x1f ? 0 :
+                                      1850 - val * 25);
+
+       case 85:                /* VRM 8.5 */
+               return((val & 0x10  ? 25 : 0) +
+                      ((val & 0x0f) > 0x04 ? 2050 : 1250) -
+                      ((val & 0x0f) * 50));
+
+       case 84:                /* VRM 8.4 */
+               val &= 0x0f;
+                               /* fall through */
+       default:                /* VRM 8.2 */
+               return(val == 0x1f ? 0 :
+                      val & 0x10  ? 5100 - (val) * 100 :
+                                    2050 - (val) * 50);
+       }
+}
+
+
+/*
+    After this point is the code to automatically determine which
+    VRM/VRD specification should be used depending on the CPU.
+*/
+
+struct vrm_model {
+       u8 vendor;
+       u8 eff_family;
+       u8 eff_model;
+       int vrm_type;
+};
+
+#define ANY 0xFF
+
+#ifdef CONFIG_X86
+
+static struct vrm_model vrm_models[] = {
+       {X86_VENDOR_AMD, 0x6, ANY, 90},         /* Athlon Duron etc */
+       {X86_VENDOR_AMD, 0xF, ANY, 24},         /* Athlon 64, Opteron */
+       {X86_VENDOR_INTEL, 0x6, 0x9, 85},       /* 0.13um too */
+       {X86_VENDOR_INTEL, 0x6, 0xB, 85},       /* Tualatin */
+       {X86_VENDOR_INTEL, 0x6, ANY, 82},       /* any P6 */
+       {X86_VENDOR_INTEL, 0x7, ANY, 0},        /* Itanium */
+       {X86_VENDOR_INTEL, 0xF, 0x0, 90},       /* P4 */
+       {X86_VENDOR_INTEL, 0xF, 0x1, 90},       /* P4 Willamette */
+       {X86_VENDOR_INTEL, 0xF, 0x2, 90},       /* P4 Northwood */
+       {X86_VENDOR_INTEL, 0xF, 0x3, 100},      /* P4 Prescott */
+       {X86_VENDOR_INTEL, 0xF, 0x4, 100},      /* P4 Prescott */
+       {X86_VENDOR_INTEL, 0x10,ANY, 0},        /* Itanium 2 */
+       {X86_VENDOR_UNKNOWN, ANY, ANY, 0}       /* stop here */
+};
+
+static int find_vrm(u8 eff_family, u8 eff_model, u8 vendor)
+{
+       int i = 0;
+
+       while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
+               if (vrm_models[i].vendor==vendor)
+                       if ((vrm_models[i].eff_family==eff_family)
+                        && ((vrm_models[i].eff_model==eff_model) ||
+                            (vrm_models[i].eff_model==ANY)))
+                               return vrm_models[i].vrm_type;
+               i++;
+       }
+
+       return 0;
+}
+
+int vid_which_vrm(void)
+{
+       struct cpuinfo_x86 *c = cpu_data;
+       u32 eax;
+       u8 eff_family, eff_model;
+       int vrm_ret;
+
+       if (c->x86 < 6)         /* Any CPU with family lower than 6 */
+               return 0;       /* doesn't have VID and/or CPUID */
+
+       eax = cpuid_eax(1);
+       eff_family = ((eax & 0x00000F00)>>8);
+       eff_model  = ((eax & 0x000000F0)>>4);
+       if (eff_family == 0xF) {        /* use extended model & family */
+               eff_family += ((eax & 0x00F00000)>>20);
+               eff_model += ((eax & 0x000F0000)>>16)<<4;
+       }
+       vrm_ret = find_vrm(eff_family,eff_model,c->x86_vendor);
+       if (vrm_ret == 0)
+               printk(KERN_INFO "hwmon-vid: Unknown VRM version of your "
+                      "x86 CPU\n");
+       return vrm_ret;
+}
+
+/* and now something completely different for the non-x86 world */
+#else
+int vid_which_vrm(void)
+{
+       printk(KERN_INFO "hwmon-vid: Unknown VRM version of your CPU\n");
+       return 0;
+}
+#endif
+
+EXPORT_SYMBOL(vid_from_reg);
+EXPORT_SYMBOL(vid_which_vrm);
+
+MODULE_AUTHOR("Rudolf Marek <r.marek@sh.cvut.cz>");
+
+MODULE_DESCRIPTION("hwmon-vid driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
new file mode 100644 (file)
index 0000000..9b41c9b
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+    hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
+
+    This file defines the sysfs class "hwmon", for use by sensors drivers.
+
+    Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
+
+    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; version 2 of the License.
+*/
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/kdev_t.h>
+#include <linux/idr.h>
+#include <linux/hwmon.h>
+
+#define HWMON_ID_PREFIX "hwmon"
+#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d"
+
+static struct class *hwmon_class;
+
+static DEFINE_IDR(hwmon_idr);
+
+/**
+ * hwmon_device_register - register w/ hwmon sysfs class
+ * @dev: the device to register
+ *
+ * hwmon_device_unregister() must be called when the class device is no
+ * longer needed.
+ *
+ * Returns the pointer to the new struct class device.
+ */
+struct class_device *hwmon_device_register(struct device *dev)
+{
+       struct class_device *cdev;
+       int id;
+
+       if (idr_pre_get(&hwmon_idr, GFP_KERNEL) == 0)
+               return ERR_PTR(-ENOMEM);
+
+       if (idr_get_new(&hwmon_idr, NULL, &id) < 0)
+               return ERR_PTR(-ENOMEM);
+
+       id = id & MAX_ID_MASK;
+       cdev = class_device_create(hwmon_class, MKDEV(0,0), dev,
+                                       HWMON_ID_FORMAT, id);
+
+       if (IS_ERR(cdev))
+               idr_remove(&hwmon_idr, id);
+
+       return cdev;
+}
+
+/**
+ * hwmon_device_unregister - removes the previously registered class device
+ *
+ * @cdev: the class device to destroy
+ */
+void hwmon_device_unregister(struct class_device *cdev)
+{
+       int id;
+
+       if (sscanf(cdev->class_id, HWMON_ID_FORMAT, &id) == 1) {
+               class_device_unregister(cdev);
+               idr_remove(&hwmon_idr, id);
+       } else
+               dev_dbg(cdev->dev,
+                       "hwmon_device_unregister() failed: bad class ID!\n");
+}
+
+static int __init hwmon_init(void)
+{
+       hwmon_class = class_create(THIS_MODULE, "hwmon");
+       if (IS_ERR(hwmon_class)) {
+               printk(KERN_ERR "hwmon.c: couldn't create sysfs class\n");
+               return PTR_ERR(hwmon_class);
+       }
+       return 0;
+}
+
+static void __exit hwmon_exit(void)
+{
+       class_destroy(hwmon_class);
+}
+
+module_init(hwmon_init);
+module_exit(hwmon_exit);
+
+EXPORT_SYMBOL_GPL(hwmon_device_register);
+EXPORT_SYMBOL_GPL(hwmon_device_unregister);
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
+MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
+MODULE_LICENSE("GPL");
+
index db20c9e47393a36bbd04b580ce92560ff6dcc331..53cc2b6d63854a835e661a0b2921640b6e36e915 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
                                        0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_2(it87, it8712);
+I2C_CLIENT_INSMOD_2(it87, it8712);
 
 #define        REG     0x2e    /* The register to read/write */
 #define        DEV     0x07    /* Register: Logical device select */
@@ -192,6 +194,7 @@ static int DIV_TO_REG(int val)
    allocated. */
 struct it87_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -218,7 +221,7 @@ struct it87_data {
 
 
 static int it87_attach_adapter(struct i2c_adapter *adapter);
-static int it87_find(int *address);
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter);
 static int it87_detect(struct i2c_adapter *adapter, int address, int kind);
 static int it87_detach_client(struct i2c_client *client);
 
@@ -239,6 +242,14 @@ static struct i2c_driver it87_driver = {
        .detach_client  = it87_detach_client,
 };
 
+static struct i2c_driver it87_isa_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "it87-isa",
+       .attach_adapter = it87_isa_attach_adapter,
+       .detach_client  = it87_detach_client,
+};
+
+
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
                char *buf)
 {
@@ -686,11 +697,16 @@ static int it87_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, it87_detect);
+       return i2c_probe(adapter, &addr_data, it87_detect);
 }
 
-/* SuperIO detection - will change normal_isa[0] if a chip is found */
-static int it87_find(int *address)
+static int it87_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+       return it87_detect(adapter, isa_address, -1);
+}
+
+/* SuperIO detection - will change isa_address if a chip is found */
+static int __init it87_find(int *address)
 {
        int err = -ENODEV;
 
@@ -721,7 +737,7 @@ exit:
        return err;
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i;
@@ -738,7 +754,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Reserve the ISA region */
        if (is_isa)
-               if (!request_region(address, IT87_EXTENT, it87_driver.name))
+               if (!request_region(address, IT87_EXTENT, it87_isa_driver.name))
                        goto ERROR0;
 
        /* Probe whether there is anything available on this address. Already
@@ -784,7 +800,7 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
        i2c_set_clientdata(new_client, data);
        new_client->addr = address;
        new_client->adapter = adapter;
-       new_client->driver = &it87_driver;
+       new_client->driver = is_isa ? &it87_isa_driver : &it87_driver;
        new_client->flags = 0;
 
        /* Now, we do the remaining detection. */
@@ -840,6 +856,12 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
        it87_init_client(new_client, data);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
        device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
        device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
@@ -897,13 +919,15 @@ int it87_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        if (data->type == it8712) {
-               data->vrm = i2c_which_vrm();
+               data->vrm = vid_which_vrm();
                device_create_file_vrm(new_client);
                device_create_file_vid(new_client);
        }
 
        return 0;
 
+ERROR3:
+       i2c_detach_client(new_client);
 ERROR2:
        kfree(data);
 ERROR1:
@@ -915,17 +939,17 @@ ERROR0:
 
 static int it87_detach_client(struct i2c_client *client)
 {
+       struct it87_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                       "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        if(i2c_is_isa_client(client))
                release_region(client->addr, IT87_EXTENT);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -1158,16 +1182,28 @@ static struct it87_data *it87_update_device(struct device *dev)
 
 static int __init sm_it87_init(void)
 {
-       int addr;
+       int addr, res;
 
        if (!it87_find(&addr)) {
-               normal_isa[0] = addr;
+               isa_address = addr;
+       }
+
+       res = i2c_add_driver(&it87_driver);
+       if (res)
+               return res;
+
+       res = i2c_isa_add_driver(&it87_isa_driver);
+       if (res) {
+               i2c_del_driver(&it87_driver);
+               return res;
        }
-       return i2c_add_driver(&it87_driver);
+
+       return 0;
 }
 
 static void __exit sm_it87_exit(void)
 {
+       i2c_isa_del_driver(&it87_isa_driver);
        i2c_del_driver(&it87_driver);
 }
 
index 7c6f9ea5a254c53614e2269a89263a4aad96184f..be5c7095ecbb2648bf86a05583373b0e9a30a157 100644 (file)
@@ -42,8 +42,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 
 static unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(lm63);
+I2C_CLIENT_INSMOD_1(lm63);
 
 /*
  * The LM63 registers
@@ -152,6 +152,7 @@ static struct i2c_driver lm63_driver = {
 
 struct lm63_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -358,7 +359,7 @@ static int lm63_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm63_detect);
+       return i2c_probe(adapter, &addr_data, lm63_detect);
 }
 
 /*
@@ -437,6 +438,12 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
        lm63_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        if (data->config & 0x04) { /* tachometer enabled */
                device_create_file(&new_client->dev,
                                   &sensor_dev_attr_fan1_input.dev_attr);
@@ -462,6 +469,8 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -505,15 +514,15 @@ static void lm63_init_client(struct i2c_client *client)
 
 static int lm63_detach_client(struct i2c_client *client)
 {
+       struct lm63_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 5be164ed278ebaf236f9b65b98663b450cef8ba5..9a3ebdf583f403ec80f4c066aa64459bfb4ccfac 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include "lm75.h"
 
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c,
                                        0x4d, 0x4e, 0x4f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm75);
+I2C_CLIENT_INSMOD_1(lm75);
 
 /* Many LM75 constants specified below */
 
@@ -46,6 +46,7 @@ SENSORS_INSMOD_1(lm75);
 /* Each client has this additional data */
 struct lm75_data {
        struct i2c_client       client;
+       struct class_device *class_dev;
        struct semaphore        update_lock;
        char                    valid;          /* !=0 if following fields are valid */
        unsigned long           last_updated;   /* In jiffies */
@@ -107,10 +108,10 @@ static int lm75_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm75_detect);
+       return i2c_probe(adapter, &addr_data, lm75_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i;
@@ -119,16 +120,6 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
        int err = 0;
        const char *name = "";
 
-       /* Make sure we aren't probing the ISA bus!! This is just a safety check
-          at this moment; i2c_detect really won't call us. */
-#ifdef DEBUG
-       if (i2c_is_isa_adapter(adapter)) {
-               dev_dbg(&adapter->dev,
-                       "lm75_detect called for an ISA bus adapter?!?\n");
-               goto exit;
-       }
-#endif
-
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
                                     I2C_FUNC_SMBUS_WORD_DATA))
                goto exit;
@@ -208,12 +199,20 @@ static int lm75_detect(struct i2c_adapter *adapter, int address, int kind)
        lm75_init_client(new_client);
        
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_temp1_max);
        device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -222,8 +221,10 @@ exit:
 
 static int lm75_detach_client(struct i2c_client *client)
 {
+       struct lm75_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->class_dev);
        i2c_detach_client(client);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
@@ -251,8 +252,12 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
 
 static void lm75_init_client(struct i2c_client *client)
 {
-       /* Initialize the LM75 chip */
-       lm75_write_value(client, LM75_REG_CONF, 0);
+       int reg;
+
+       /* Enable if in shutdown mode */
+       reg = lm75_read_value(client, LM75_REG_CONF);
+       if (reg >= 0 && (reg & 0x01))
+               lm75_write_value(client, LM75_REG_CONF, reg & 0xfe);
 }
 
 static struct lm75_data *lm75_update_device(struct device *dev)
index 63e3f2fb4c21dd4ef6b2063a993e4b5f2e237672..af7dc650ee1506878901453ea51bc75dee764392 100644 (file)
@@ -25,7 +25,7 @@
     which contains this code, we don't worry about the wasted space.
 */
 
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
 
 /* straight from the datasheet */
 #define LM75_TEMP_MIN (-55000)
index b98f449529976083b38c881f5cc9997050d500a7..866eab96a6f6f6594374037bda6eeb08c5a39c1a 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm77);
+I2C_CLIENT_INSMOD_1(lm77);
 
 /* The LM77 registers */
 #define LM77_REG_TEMP          0x00
@@ -51,6 +50,7 @@ SENSORS_INSMOD_1(lm77);
 /* Each client has this additional data */
 struct lm77_data {
        struct i2c_client       client;
+       struct class_device *class_dev;
        struct semaphore        update_lock;
        char                    valid;
        unsigned long           last_updated;   /* In jiffies */
@@ -208,10 +208,10 @@ static int lm77_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm77_detect);
+       return i2c_probe(adapter, &addr_data, lm77_detect);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        struct i2c_client *new_client;
@@ -317,6 +317,12 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
        lm77_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
        device_create_file(&new_client->dev, &dev_attr_temp1_crit);
        device_create_file(&new_client->dev, &dev_attr_temp1_min);
@@ -327,6 +333,8 @@ static int lm77_detect(struct i2c_adapter *adapter, int address, int kind)
        device_create_file(&new_client->dev, &dev_attr_alarms);
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -335,8 +343,10 @@ exit:
 
 static int lm77_detach_client(struct i2c_client *client)
 {
+       struct lm77_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->class_dev);
        i2c_detach_client(client);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 29241469dcbac09d2617c365e7b5388fc6908308..f6730dc3573b68096814ccff7e8a898aae45122a 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
 /* Addresses to scan */
@@ -31,10 +34,10 @@ static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24,
                                        0x25, 0x26, 0x27, 0x28, 0x29,
                                        0x2a, 0x2b, 0x2c, 0x2d, 0x2e,
                                        0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_3(lm78, lm78j, lm79);
+I2C_CLIENT_INSMOD_2(lm78, lm79);
 
 /* Many LM78 constants specified below */
 
@@ -104,13 +107,6 @@ static inline int TEMP_FROM_REG(s8 val)
        return val * 1000;
 }
 
-/* VID: mV
-   REG: (see doc/vid) */
-static inline int VID_FROM_REG(u8 val)
-{
-       return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
-}
-
 #define DIV_FROM_REG(val) (1 << (val))
 
 /* There are some complications in a module like this. First off, LM78 chips
@@ -134,6 +130,7 @@ static inline int VID_FROM_REG(u8 val)
    allocated. */
 struct lm78_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -156,6 +153,7 @@ struct lm78_data {
 
 
 static int lm78_attach_adapter(struct i2c_adapter *adapter);
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
 static int lm78_detach_client(struct i2c_client *client);
 
@@ -174,6 +172,14 @@ static struct i2c_driver lm78_driver = {
        .detach_client  = lm78_detach_client,
 };
 
+static struct i2c_driver lm78_isa_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "lm78-isa",
+       .attach_adapter = lm78_isa_attach_adapter,
+       .detach_client  = lm78_detach_client,
+};
+
+
 /* 7 Voltages */
 static ssize_t show_in(struct device *dev, char *buf, int nr)
 {
@@ -445,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
-       return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
+       return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
@@ -465,10 +471,15 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm78_detect);
+       return i2c_probe(adapter, &addr_data, lm78_detect);
+}
+
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+       return lm78_detect(adapter, isa_address, -1);
 }
 
-/* This function is called by i2c_detect */
+/* This function is called by i2c_probe */
 int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i, err;
@@ -485,7 +496,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Reserve the ISA region */
        if (is_isa)
-               if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
+               if (!request_region(address, LM78_EXTENT,
+                                   lm78_isa_driver.name)) {
                        err = -EBUSY;
                        goto ERROR0;
                }
@@ -540,7 +552,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        i2c_set_clientdata(new_client, data);
        new_client->addr = address;
        new_client->adapter = adapter;
-       new_client->driver = &lm78_driver;
+       new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
        new_client->flags = 0;
 
        /* Now, we do the remaining detection. */
@@ -559,10 +571,9 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        /* Determine the chip type. */
        if (kind <= 0) {
                i = lm78_read_value(new_client, LM78_REG_CHIPID);
-               if (i == 0x00 || i == 0x20)
+               if (i == 0x00 || i == 0x20      /* LM78 */
+                || i == 0x40)                  /* LM78-J */
                        kind = lm78;
-               else if (i == 0x40)
-                       kind = lm78j;
                else if ((i & 0xfe) == 0xc0)
                        kind = lm79;
                else {
@@ -578,8 +589,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        if (kind == lm78) {
                client_name = "lm78";
-       } else if (kind == lm78j) {
-               client_name = "lm78-j";
        } else if (kind == lm79) {
                client_name = "lm79";
        }
@@ -605,6 +614,12 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in0_min);
        device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -643,6 +658,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+ERROR3:
+       i2c_detach_client(new_client);
 ERROR2:
        kfree(data);
 ERROR1:
@@ -654,18 +671,18 @@ ERROR0:
 
 static int lm78_detach_client(struct i2c_client *client)
 {
+       struct lm78_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                   "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        if(i2c_is_isa_client(client))
                release_region(client->addr, LM78_EXTENT);
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -777,18 +794,31 @@ static struct lm78_data *lm78_update_device(struct device *dev)
 
 static int __init sm_lm78_init(void)
 {
-       return i2c_add_driver(&lm78_driver);
+       int res;
+
+       res = i2c_add_driver(&lm78_driver);
+       if (res)
+               return res;
+
+       res = i2c_isa_add_driver(&lm78_isa_driver);
+       if (res) {
+               i2c_del_driver(&lm78_driver);
+               return res;
+       }
+
+       return 0;
 }
 
 static void __exit sm_lm78_exit(void)
 {
+       i2c_isa_del_driver(&lm78_isa_driver);
        i2c_del_driver(&lm78_driver);
 }
 
 
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
+MODULE_DESCRIPTION("LM78/LM79 driver");
 MODULE_LICENSE("GPL");
 
 module_init(sm_lm78_init);
index 8100595feb44640133c6ae6aa7308839f35c7711..83af8b3a0cac02ba04ef70f1ec4b8f118de210b5 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c,
                                        0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm80);
+I2C_CLIENT_INSMOD_1(lm80);
 
 /* Many LM80 constants specified below */
 
@@ -107,6 +107,7 @@ static inline long TEMP_FROM_REG(u16 temp)
 
 struct lm80_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid;             /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
@@ -389,7 +390,7 @@ static int lm80_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm80_detect);
+       return i2c_probe(adapter, &addr_data, lm80_detect);
 }
 
 int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
@@ -451,6 +452,12 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
        data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto error_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_min);
        device_create_file(&new_client->dev, &dev_attr_in1_min);
        device_create_file(&new_client->dev, &dev_attr_in2_min);
@@ -487,6 +494,8 @@ int lm80_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+error_detach:
+       i2c_detach_client(new_client);
 error_free:
        kfree(data);
 exit:
@@ -495,15 +504,15 @@ exit:
 
 static int lm80_detach_client(struct i2c_client *client)
 {
+       struct lm80_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index a49008b444c8ef483f3e6ec933578c3a9e57e240..d74b2c20c719376eea2c8231938f66be28a5f9d8 100644 (file)
@@ -32,8 +32,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
@@ -45,13 +46,12 @@ static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
                                        0x29, 0x2a, 0x2b,
                                        0x4c, 0x4d, 0x4e,
                                        I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(lm83);
+I2C_CLIENT_INSMOD_1(lm83);
 
 /*
  * The LM83 registers
@@ -138,6 +138,7 @@ static struct i2c_driver lm83_driver = {
 
 struct lm83_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -212,7 +213,7 @@ static int lm83_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm83_detect);
+       return i2c_probe(adapter, &addr_data, lm83_detect);
 }
 
 /*
@@ -312,6 +313,12 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
         */
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev,
                           &sensor_dev_attr_temp1_input.dev_attr);
        device_create_file(&new_client->dev,
@@ -340,6 +347,8 @@ static int lm83_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -348,15 +357,15 @@ exit:
 
 static int lm83_detach_client(struct i2c_client *client)
 {
+       struct lm83_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                   "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index b4d7fd41826478a241d50535a70bbbf0507c8de4..ab214df9624bc423376bef632b4a87d0d1f2cf96 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
+I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
 
 /* The LM85 registers */
 
@@ -281,15 +281,6 @@ static int ZONE_TO_REG( int zone )
 #define PPR_TO_REG(val,fan) (SENSORS_LIMIT((val)-1,0,3)<<(fan *2))
 #define PPR_FROM_REG(val,fan) ((((val)>>(fan * 2))&0x03)+1)
 
-/* i2c-vid.h defines vid_from_reg() */
-#define VID_FROM_REG(val,vrm) (vid_from_reg((val),(vrm)))
-
-/* Unlike some other drivers we DO NOT set initial limits.  Use
- * the config file to set limits.  Some users have reported
- * motherboards shutting down when we set limits in a previous
- * version of the driver.
- */
-
 /* Chip sampling rates
  *
  * Some sensors are not updated more frequently than once per second
@@ -339,6 +330,7 @@ struct lm85_autofan {
 
 struct lm85_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -1019,7 +1011,7 @@ int lm85_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm85_detect);
+       return i2c_probe(adapter, &addr_data, lm85_detect);
 }
 
 int lm85_detect(struct i2c_adapter *adapter, int address,
@@ -1031,11 +1023,6 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
        int err = 0;
        const char *type_name = "";
 
-       if (i2c_is_isa_adapter(adapter)) {
-               /* This chip has no ISA interface */
-               goto ERROR0 ;
-       };
-
        if (!i2c_check_functionality(adapter,
                                        I2C_FUNC_SMBUS_BYTE_DATA)) {
                /* We need to be able to do byte I/O */
@@ -1160,12 +1147,18 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
                goto ERROR1;
 
        /* Set the VRM version */
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        /* Initialize the LM85 chip */
        lm85_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR2;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_fan1_input);
        device_create_file(&new_client->dev, &dev_attr_fan2_input);
        device_create_file(&new_client->dev, &dev_attr_fan3_input);
@@ -1235,6 +1228,8 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
        return 0;
 
        /* Error out and cleanup code */
+    ERROR2:
+       i2c_detach_client(new_client);
     ERROR1:
        kfree(data);
     ERROR0:
@@ -1243,8 +1238,10 @@ int lm85_detect(struct i2c_adapter *adapter, int address,
 
 int lm85_detach_client(struct i2c_client *client)
 {
+       struct lm85_data *data = i2c_get_clientdata(client);
+       hwmon_device_unregister(data->class_dev);
        i2c_detach_client(client);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 1921ed1af182df9f05dc68b114e7115f51009bea..dca996de4c331e5eae87c3a868fb47c46ca9b3e6 100644 (file)
@@ -57,8 +57,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(lm87);
+I2C_CLIENT_INSMOD_1(lm87);
 
 /*
  * The LM87 registers
@@ -175,6 +175,7 @@ static struct i2c_driver lm87_driver = {
 
 struct lm87_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* In jiffies */
@@ -537,7 +538,7 @@ static int lm87_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm87_detect);
+       return i2c_probe(adapter, &addr_data, lm87_detect);
 }
 
 /*
@@ -608,6 +609,12 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
        data->in_scale[7] = 1875;
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in1_input);
        device_create_file(&new_client->dev, &dev_attr_in1_min);
        device_create_file(&new_client->dev, &dev_attr_in1_max);
@@ -673,6 +680,8 @@ static int lm87_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -685,7 +694,7 @@ static void lm87_init_client(struct i2c_client *client)
        u8 config;
 
        data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE);
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        config = lm87_read_value(client, LM87_REG_CONFIG);
        if (!(config & 0x01)) {
@@ -719,15 +728,15 @@ static void lm87_init_client(struct i2c_client *client)
 
 static int lm87_detach_client(struct i2c_client *client)
 {
+       struct lm87_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index a67dcadf7cb04381882b71185786fa1c945677d2..14de05fcd431e76c87c4a7ffc2e65c4d1e1252a4 100644 (file)
@@ -75,8 +75,9 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /*
  * Addresses to scan
  */
 
 static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
+I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
 
 /*
  * The LM90 registers
@@ -200,6 +200,7 @@ static struct i2c_driver lm90_driver = {
 
 struct lm90_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -352,7 +353,7 @@ static int lm90_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm90_detect);
+       return i2c_probe(adapter, &addr_data, lm90_detect);
 }
 
 /*
@@ -500,6 +501,12 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
        lm90_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev,
                           &sensor_dev_attr_temp1_input.dev_attr);
        device_create_file(&new_client->dev,
@@ -524,6 +531,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -547,15 +556,15 @@ static void lm90_init_client(struct i2c_client *client)
 
 static int lm90_detach_client(struct i2c_client *client)
 {
+       struct lm90_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 215c8e40ffdd4041e114aa7912f93e9292b61be3..647b7c7cd575df129ed9ed7bbb7535e2d1422232 100644 (file)
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* The LM92 and MAX6635 have 2 two-state pins for address selection,
    resulting in 4 possible addresses. */
 static unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
                                       I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /* Insmod parameters */
-SENSORS_INSMOD_1(lm92);
+I2C_CLIENT_INSMOD_1(lm92);
 
 /* The LM92 registers */
 #define LM92_REG_CONFIG                        0x01 /* 8-bit, RW */
@@ -96,6 +95,7 @@ static struct i2c_driver lm92_driver;
 /* Client data (each client gets its own) */
 struct lm92_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -359,6 +359,12 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
        lm92_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
        device_create_file(&new_client->dev, &dev_attr_temp1_crit);
        device_create_file(&new_client->dev, &dev_attr_temp1_crit_hyst);
@@ -370,6 +376,8 @@ static int lm92_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -380,20 +388,20 @@ static int lm92_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm92_detect);
+       return i2c_probe(adapter, &addr_data, lm92_detect);
 }
 
 static int lm92_detach_client(struct i2c_client *client)
 {
+       struct lm92_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index 3c159f1d49ee3e6e0bf6b8acd5ccbfa8093ec938..16bf71f3a04d941f92391e64f8a6980b2e903315 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
                                        0x29, 0x2a, 0x2b,
                                        0x4c, 0x4d, 0x4e,
                                        I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(max1619);
+I2C_CLIENT_INSMOD_1(max1619);
 
 /*
  * The MAX1619 registers
@@ -104,6 +103,7 @@ static struct i2c_driver max1619_driver = {
 
 struct max1619_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -179,7 +179,7 @@ static int max1619_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, max1619_detect);
+       return i2c_probe(adapter, &addr_data, max1619_detect);
 }
 
 /*
@@ -275,6 +275,12 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
        max1619_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
        device_create_file(&new_client->dev, &dev_attr_temp2_input);
        device_create_file(&new_client->dev, &dev_attr_temp2_min);
@@ -285,6 +291,8 @@ static int max1619_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -308,15 +316,15 @@ static void max1619_init_client(struct i2c_client *client)
 
 static int max1619_detach_client(struct i2c_client *client)
 {
+       struct max1619_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index fa4032d53b790b3e08dd6fdf6d730e4258ae05e5..08fcb5aea764317721235b58d48a58ce4c618f1a 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{ NULL }};
 static u8 devid;
-static unsigned int extra_isa[3];
+static unsigned short address;
+static unsigned short extra_isa[3];
 static u8 confreg[4];
 
 enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
-static struct i2c_address_data addr_data = {
-       .normal_i2c             = normal_i2c,
-       .normal_isa             = normal_isa,
-       .forces                 = forces,
-};
 
 static int init = 1;
 module_param(init, int, 0);
@@ -186,6 +181,7 @@ static inline u8 PWM_TO_REG(int val, int inv)
 
 struct pc87360_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        struct semaphore update_lock;
        char valid;             /* !=0 if following fields are valid */
@@ -224,8 +220,7 @@ struct pc87360_data {
  * Functions declaration
  */
 
-static int pc87360_attach_adapter(struct i2c_adapter *adapter);
-static int pc87360_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pc87360_detect(struct i2c_adapter *adapter);
 static int pc87360_detach_client(struct i2c_client *client);
 
 static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
@@ -242,8 +237,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
 static struct i2c_driver pc87360_driver = {
        .owner          = THIS_MODULE,
        .name           = "pc87360",
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = pc87360_attach_adapter,
+       .attach_adapter = pc87360_detect,
        .detach_client  = pc87360_detach_client,
 };
 
@@ -632,12 +626,7 @@ static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL);
  * Device detection, registration and update
  */
 
-static int pc87360_attach_adapter(struct i2c_adapter *adapter)
-{
-       return i2c_detect(adapter, &addr_data, pc87360_detect);
-}
-
-static int pc87360_find(int sioaddr, u8 *devid, int *address)
+static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses)
 {
        u16 val;
        int i;
@@ -683,7 +672,7 @@ static int pc87360_find(int sioaddr, u8 *devid, int *address)
                        continue;
                }
 
-               address[i] = val;
+               addresses[i] = val;
 
                if (i==0) { /* Fans */
                        confreg[0] = superio_inb(sioaddr, 0xF0);
@@ -727,9 +716,7 @@ static int pc87360_find(int sioaddr, u8 *devid, int *address)
        return 0;
 }
 
-/* We don't really care about the address.
-   Read from extra_isa instead. */
-int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
+static int pc87360_detect(struct i2c_adapter *adapter)
 {
        int i;
        struct i2c_client *new_client;
@@ -738,9 +725,6 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
        const char *name = "pc87360";
        int use_thermistors = 0;
 
-       if (!i2c_is_isa_adapter(adapter))
-               return -ENODEV;
-
        if (!(data = kmalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
                return -ENOMEM;
        memset(data, 0x00, sizeof(struct pc87360_data));
@@ -838,6 +822,12 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        if (data->innr) {
                device_create_file(&new_client->dev, &dev_attr_in0_input);
                device_create_file(&new_client->dev, &dev_attr_in1_input);
@@ -974,6 +964,8 @@ int pc87360_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+ERROR3:
+       i2c_detach_client(new_client);
 ERROR2:
        for (i = 0; i < 3; i++) {
                if (data->address[i]) {
@@ -990,11 +982,10 @@ static int pc87360_detach_client(struct i2c_client *client)
        struct pc87360_data *data = i2c_get_clientdata(client);
        int i;
 
-       if ((i = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((i = i2c_detach_client(client)))
                return i;
-       }
 
        for (i = 0; i < 3; i++) {
                if (data->address[i]) {
@@ -1320,23 +1311,23 @@ static int __init pc87360_init(void)
        /* Arbitrarily pick one of the addresses */
        for (i = 0; i < 3; i++) {
                if (extra_isa[i] != 0x0000) {
-                       normal_isa[0] = extra_isa[i];
+                       address = extra_isa[i];
                        break;
                }
        }
 
-       if (normal_isa[0] == 0x0000) {
+       if (address == 0x0000) {
                printk(KERN_WARNING "pc87360: No active logical device, "
                       "module not inserted.\n");
                return -ENODEV;
        }
 
-       return i2c_add_driver(&pc87360_driver);
+       return i2c_isa_add_driver(&pc87360_driver);
 }
 
 static void __exit pc87360_exit(void)
 {
-       i2c_del_driver(&pc87360_driver);
+       i2c_isa_del_driver(&pc87360_driver);
 }
 
 
index 6bbfc8fb4f13247d61cedb2124a74b5df4589620..8610bce08244d1bb3f74dcca18ef48112c717073 100644 (file)
@@ -55,7 +55,9 @@
 #include <linux/ioport.h>
 #include <linux/pci.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
 #include <asm/io.h>
@@ -68,14 +70,10 @@ module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
                 "Initialize the base address of the sensors");
 
-/* Addresses to scan.
+/* Device address
    Note that we can't determine the ISA address until we have initialized
    our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(sis5595);
+static unsigned short address;
 
 /* Many SIS5595 constants specified below */
 
@@ -168,6 +166,7 @@ static inline u8 DIV_TO_REG(int val)
    allocated. */
 struct sis5595_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
 
        struct semaphore update_lock;
@@ -190,8 +189,7 @@ struct sis5595_data {
 
 static struct pci_dev *s_bridge;       /* pointer to the (only) sis5595 */
 
-static int sis5595_attach_adapter(struct i2c_adapter *adapter);
-static int sis5595_detect(struct i2c_adapter *adapter, int address, int kind);
+static int sis5595_detect(struct i2c_adapter *adapter);
 static int sis5595_detach_client(struct i2c_client *client);
 
 static int sis5595_read_value(struct i2c_client *client, u8 register);
@@ -202,9 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
 static struct i2c_driver sis5595_driver = {
        .owner          = THIS_MODULE,
        .name           = "sis5595",
-       .id             = I2C_DRIVERID_SIS5595,
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = sis5595_attach_adapter,
+       .attach_adapter = sis5595_detect,
        .detach_client  = sis5595_detach_client,
 };
 
@@ -476,14 +472,7 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
  
 /* This is called when the module is loaded */
-static int sis5595_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-       return i2c_detect(adapter, &addr_data, sis5595_detect);
-}
-
-int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
+static int sis5595_detect(struct i2c_adapter *adapter)
 {
        int err = 0;
        int i;
@@ -492,10 +481,6 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
        char val;
        u16 a;
 
-       /* Make sure we are probing the ISA bus!!  */
-       if (!i2c_is_isa_adapter(adapter))
-               goto exit;
-
        if (force_addr)
                address = force_addr & ~(SIS5595_EXTENT - 1);
        /* Reserve the ISA region */
@@ -578,6 +563,12 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in0_min);
        device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -608,7 +599,9 @@ int sis5595_detect(struct i2c_adapter *adapter, int address, int kind)
                device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
        }
        return 0;
-       
+
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit_release:
@@ -619,18 +612,17 @@ exit:
 
 static int sis5595_detach_client(struct i2c_client *client)
 {
+       struct sis5595_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                   "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       if (i2c_is_isa_client(client))
-               release_region(client->addr, SIS5595_EXTENT);
+       release_region(client->addr, SIS5595_EXTENT);
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -745,7 +737,6 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
 {
        u16 val;
        int *i;
-       int addr = 0;
 
        for (i = blacklist; *i != 0; i++) {
                struct pci_dev *dev;
@@ -761,22 +752,19 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
            pci_read_config_word(dev, SIS5595_BASE_REG, &val))
                return -ENODEV;
        
-       addr = val & ~(SIS5595_EXTENT - 1);
-       if (addr == 0 && force_addr == 0) {
+       address = val & ~(SIS5595_EXTENT - 1);
+       if (address == 0 && force_addr == 0) {
                dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
                return -ENODEV;
        }
-       if (force_addr)
-               addr = force_addr;      /* so detect will get called */
 
-       if (!addr) {
+       if (!address) {
                dev_err(&dev->dev,"No SiS 5595 sensors found.\n");
                return -ENODEV;
        }
-       normal_isa[0] = addr;
 
        s_bridge = pci_dev_get(dev);
-       if (i2c_add_driver(&sis5595_driver)) {
+       if (i2c_isa_add_driver(&sis5595_driver)) {
                pci_dev_put(s_bridge);
                s_bridge = NULL;
        }
@@ -803,7 +791,7 @@ static void __exit sm_sis5595_exit(void)
 {
        pci_unregister_driver(&sis5595_pci_driver);
        if (s_bridge != NULL) {
-               i2c_del_driver(&sis5595_driver);
+               i2c_isa_del_driver(&sis5595_driver);
                pci_dev_put(s_bridge);
                s_bridge = NULL;
        }
index fdeeb3ab6f2f3e9146b607ddc00c5d3ffd239bed..7fe71576dea4b7416e6b15ae387e56dc6238da1d 100644 (file)
 #include <linux/ioport.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <asm/io.h>
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
 /* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47b397 };
-static struct i2c_address_data addr_data = {
-       .normal_i2c             = normal_i2c,
-       .normal_isa             = normal_isa,
-       .probe                  = normal_i2c,           /* cheat */
-       .ignore                 = normal_i2c,           /* cheat */
-       .forces                 = forces,
-};
+static unsigned short address;
 
 /* Super-I/0 registers and commands */
 
@@ -100,6 +91,7 @@ static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80};
 
 struct smsc47b397_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
 
        struct semaphore update_lock;
@@ -215,52 +207,40 @@ sysfs_fan(4);
 #define device_create_file_fan(client, num) \
        device_create_file(&client->dev, &dev_attr_fan##num##_input)
 
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind);
-
-static int smsc47b397_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-       return i2c_detect(adapter, &addr_data, smsc47b397_detect);
-}
-
 static int smsc47b397_detach_client(struct i2c_client *client)
 {
+       struct smsc47b397_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        release_region(client->addr, SMSC_EXTENT);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
 
+static int smsc47b397_detect(struct i2c_adapter *adapter);
+
 static struct i2c_driver smsc47b397_driver = {
        .owner          = THIS_MODULE,
        .name           = "smsc47b397",
-       .id             = I2C_DRIVERID_SMSC47B397,
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = smsc47b397_attach_adapter,
+       .attach_adapter = smsc47b397_detect,
        .detach_client  = smsc47b397_detach_client,
 };
 
-static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
+static int smsc47b397_detect(struct i2c_adapter *adapter)
 {
        struct i2c_client *new_client;
        struct smsc47b397_data *data;
        int err = 0;
 
-       if (!i2c_is_isa_adapter(adapter)) {
-               return 0;
-       }
-
-       if (!request_region(addr, SMSC_EXTENT, smsc47b397_driver.name)) {
-               dev_err(&adapter->dev, "Region 0x%x already in use!\n", addr);
+       if (!request_region(address, SMSC_EXTENT, smsc47b397_driver.name)) {
+               dev_err(&adapter->dev, "Region 0x%x already in use!\n",
+                       address);
                return -EBUSY;
        }
 
@@ -272,7 +252,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
 
        new_client = &data->client;
        i2c_set_clientdata(new_client, data);
-       new_client->addr = addr;
+       new_client->addr = address;
        init_MUTEX(&data->lock);
        new_client->adapter = adapter;
        new_client->driver = &smsc47b397_driver;
@@ -285,6 +265,12 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
        if ((err = i2c_attach_client(new_client)))
                goto error_free;
 
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto error_detach;
+       }
+
        device_create_file_temp(new_client, 1);
        device_create_file_temp(new_client, 2);
        device_create_file_temp(new_client, 3);
@@ -297,14 +283,16 @@ static int smsc47b397_detect(struct i2c_adapter *adapter, int addr, int kind)
 
        return 0;
 
+error_detach:
+       i2c_detach_client(new_client);
 error_free:
        kfree(data);
 error_release:
-       release_region(addr, SMSC_EXTENT);
+       release_region(address, SMSC_EXTENT);
        return err;
 }
 
-static int __init smsc47b397_find(unsigned int *addr)
+static int __init smsc47b397_find(unsigned short *addr)
 {
        u8 id, rev;
 
@@ -333,15 +321,15 @@ static int __init smsc47b397_init(void)
 {
        int ret;
 
-       if ((ret = smsc47b397_find(normal_isa)))
+       if ((ret = smsc47b397_find(&address)))
                return ret;
 
-       return i2c_add_driver(&smsc47b397_driver);
+       return i2c_isa_add_driver(&smsc47b397_driver);
 }
 
 static void __exit smsc47b397_exit(void)
 {
-       i2c_del_driver(&smsc47b397_driver);
+       i2c_isa_del_driver(&smsc47b397_driver);
 }
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
index 7166ad0b2fda666e5ace936c0b3960de9bbdd7b0..7e699a8ede262916369a88c57001f6de86eafbad 100644 (file)
 #include <linux/ioport.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <asm/io.h>
 
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
 /* Address is autodetected, there is no default value */
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-static struct i2c_force_data forces[] = {{NULL}};
-
-enum chips { any_chip, smsc47m1 };
-static struct i2c_address_data addr_data = {
-       .normal_i2c             = normal_i2c,
-       .normal_isa             = normal_isa,
-       .forces                 = forces,
-};
+static unsigned short address;
 
 /* Super-I/0 registers and commands */
 
@@ -108,6 +101,7 @@ superio_exit(void)
 
 struct smsc47m1_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
 
        struct semaphore update_lock;
@@ -121,9 +115,7 @@ struct smsc47m1_data {
 };
 
 
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter);
-static int smsc47m1_find(int *address);
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind);
+static int smsc47m1_detect(struct i2c_adapter *adapter);
 static int smsc47m1_detach_client(struct i2c_client *client);
 
 static int smsc47m1_read_value(struct i2c_client *client, u8 reg);
@@ -136,9 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 static struct i2c_driver smsc47m1_driver = {
        .owner          = THIS_MODULE,
        .name           = "smsc47m1",
-       .id             = I2C_DRIVERID_SMSC47M1,
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = smsc47m1_attach_adapter,
+       .attach_adapter = smsc47m1_detect,
        .detach_client  = smsc47m1_detach_client,
 };
 
@@ -354,14 +344,7 @@ fan_present(2);
 
 static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL);
 
-static int smsc47m1_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-       return i2c_detect(adapter, &addr_data, smsc47m1_detect);
-}
-
-static int smsc47m1_find(int *address)
+static int __init smsc47m1_find(unsigned short *addr)
 {
        u8 val;
 
@@ -388,10 +371,10 @@ static int smsc47m1_find(int *address)
        }
 
        superio_select();
-       *address = (superio_inb(SUPERIO_REG_BASE) << 8)
-                |  superio_inb(SUPERIO_REG_BASE + 1);
+       *addr = (superio_inb(SUPERIO_REG_BASE) << 8)
+             |  superio_inb(SUPERIO_REG_BASE + 1);
        val = superio_inb(SUPERIO_REG_ACT);
-       if (*address == 0 || (val & 0x01) == 0) {
+       if (*addr == 0 || (val & 0x01) == 0) {
                printk(KERN_INFO "smsc47m1: Device is disabled, will not use\n");
                superio_exit();
                return -ENODEV;
@@ -401,17 +384,13 @@ static int smsc47m1_find(int *address)
        return 0;
 }
 
-static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
+static int smsc47m1_detect(struct i2c_adapter *adapter)
 {
        struct i2c_client *new_client;
        struct smsc47m1_data *data;
        int err = 0;
        int fan1, fan2, pwm1, pwm2;
 
-       if (!i2c_is_isa_adapter(adapter)) {
-               return 0;
-       }
-
        if (!request_region(address, SMSC_EXTENT, smsc47m1_driver.name)) {
                dev_err(&adapter->dev, "Region 0x%x already in use!\n", address);
                return -EBUSY;
@@ -461,6 +440,13 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
           function. */
        smsc47m1_update_device(&new_client->dev, 1);
 
+       /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto error_detach;
+       }
+
        if (fan1) {
                device_create_file(&new_client->dev, &dev_attr_fan1_input);
                device_create_file(&new_client->dev, &dev_attr_fan1_min);
@@ -494,6 +480,8 @@ static int smsc47m1_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+error_detach:
+       i2c_detach_client(new_client);
 error_free:
        kfree(data);
 error_release:
@@ -503,16 +491,16 @@ error_release:
 
 static int smsc47m1_detach_client(struct i2c_client *client)
 {
+       struct smsc47m1_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        release_region(client->addr, SMSC_EXTENT);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -573,16 +561,16 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 
 static int __init sm_smsc47m1_init(void)
 {
-       if (smsc47m1_find(normal_isa)) {
+       if (smsc47m1_find(&address)) {
                return -ENODEV;
        }
 
-       return i2c_add_driver(&smsc47m1_driver);
+       return i2c_isa_add_driver(&smsc47m1_driver);
 }
 
 static void __exit sm_smsc47m1_exit(void)
 {
-       i2c_del_driver(&smsc47m1_driver);
+       i2c_isa_del_driver(&smsc47m1_driver);
 }
 
 MODULE_AUTHOR("Mark D. Studebaker <mdsxyz123@yahoo.com>");
index 164d47948390d39206537b206c5e11c9a2c6faa1..eb84997627c8245456ab40c3d402d72b51104ce9 100644 (file)
@@ -35,7 +35,9 @@
 #include <linux/pci.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <asm/io.h>
 
@@ -47,14 +49,10 @@ module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
                 "Initialize the base address of the sensors");
 
-/* Addresses to scan.
+/* Device address
    Note that we can't determine the ISA address until we have initialized
    our module */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0000, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(via686a);
+static unsigned short address;
 
 /*
    The Via 686a southbridge has a LM78-like chip integrated on the same IC.
@@ -297,6 +295,7 @@ static inline long TEMP_FROM_REG10(u16 val)
    via686a client is allocated. */
 struct via686a_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid;             /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
@@ -315,8 +314,7 @@ struct via686a_data {
 
 static struct pci_dev *s_bridge;       /* pointer to the (only) via686a */
 
-static int via686a_attach_adapter(struct i2c_adapter *adapter);
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind);
+static int via686a_detect(struct i2c_adapter *adapter);
 static int via686a_detach_client(struct i2c_client *client);
 
 static inline int via686a_read_value(struct i2c_client *client, u8 reg)
@@ -576,22 +574,13 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 static struct i2c_driver via686a_driver = {
        .owner          = THIS_MODULE,
        .name           = "via686a",
-       .id             = I2C_DRIVERID_VIA686A,
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = via686a_attach_adapter,
+       .attach_adapter = via686a_detect,
        .detach_client  = via686a_detach_client,
 };
 
 
 /* This is called when the module is loaded */
-static int via686a_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-       return i2c_detect(adapter, &addr_data, via686a_detect);
-}
-
-static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
+static int via686a_detect(struct i2c_adapter *adapter)
 {
        struct i2c_client *new_client;
        struct via686a_data *data;
@@ -599,13 +588,6 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
        const char client_name[] = "via686a";
        u16 val;
 
-       /* Make sure we are probing the ISA bus!!  */
-       if (!i2c_is_isa_adapter(adapter)) {
-               dev_err(&adapter->dev,
-               "via686a_detect called for an I2C bus adapter?!?\n");
-               return 0;
-       }
-
        /* 8231 requires multiple of 256, we enforce that on 686 as well */
        if (force_addr)
                address = force_addr & 0xFF00;
@@ -637,7 +619,7 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
 
        if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
                err = -ENOMEM;
-               goto ERROR0;
+               goto exit_release;
        }
        memset(data, 0, sizeof(struct via686a_data));
 
@@ -655,12 +637,18 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
        init_MUTEX(&data->update_lock);
        /* Tell the I2C layer a new client has arrived */
        if ((err = i2c_attach_client(new_client)))
-               goto ERROR3;
+               goto exit_free;
 
        /* Initialize the VIA686A chip */
        via686a_init_client(new_client);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in1_input);
        device_create_file(&new_client->dev, &dev_attr_in2_input);
@@ -695,25 +683,27 @@ static int via686a_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
-ERROR3:
+exit_detach:
+       i2c_detach_client(new_client);
+exit_free:
        kfree(data);
-ERROR0:
+exit_release:
        release_region(address, VIA686A_EXTENT);
        return err;
 }
 
 static int via686a_detach_client(struct i2c_client *client)
 {
+       struct via686a_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-               "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        release_region(client->addr, VIA686A_EXTENT);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -810,29 +800,25 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
                                       const struct pci_device_id *id)
 {
        u16 val;
-       int addr = 0;
 
        if (PCIBIOS_SUCCESSFUL !=
            pci_read_config_word(dev, VIA686A_BASE_REG, &val))
                return -ENODEV;
 
-       addr = val & ~(VIA686A_EXTENT - 1);
-       if (addr == 0 && force_addr == 0) {
+       address = val & ~(VIA686A_EXTENT - 1);
+       if (address == 0 && force_addr == 0) {
                dev_err(&dev->dev, "base address not set - upgrade BIOS "
                        "or use force_addr=0xaddr\n");
                return -ENODEV;
        }
-       if (force_addr)
-               addr = force_addr;      /* so detect will get called */
 
-       if (!addr) {
+       if (!address) {
                dev_err(&dev->dev, "No Via 686A sensors found.\n");
                return -ENODEV;
        }
-       normal_isa[0] = addr;
 
        s_bridge = pci_dev_get(dev);
-       if (i2c_add_driver(&via686a_driver)) {
+       if (i2c_isa_add_driver(&via686a_driver)) {
                pci_dev_put(s_bridge);
                s_bridge = NULL;
        }
@@ -859,7 +845,7 @@ static void __exit sm_via686a_exit(void)
 {
        pci_unregister_driver(&via686a_pci_driver);
        if (s_bridge != NULL) {
-               i2c_del_driver(&via686a_driver);
+               i2c_isa_del_driver(&via686a_driver);
                pci_dev_put(s_bridge);
                s_bridge = NULL;
        }
index 8a40b6976e1ad25838a37c70c49e4235a1ea3281..b60efe8f8b26691a70bc64f5617d362b68e7a2be 100644 (file)
@@ -9,6 +9,9 @@
     Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help
     in testing and debugging this driver.
 
+    This driver also supports the W83627EHG, which is the lead-free
+    version of the W83627EHF.
+
     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
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include "lm75.h"
 
-/* Addresses to scan
-   The actual ISA address is read from Super-I/O configuration space */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
-
-/* Insmod parameters */
-SENSORS_INSMOD_1(w83627ehf);
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
 
 /*
  * Super-I/O constants and functions
@@ -174,6 +174,7 @@ temp1_to_reg(int temp)
 
 struct w83627ehf_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
 
        struct semaphore update_lock;
@@ -666,15 +667,12 @@ static void w83627ehf_init_client(struct i2c_client *client)
        }
 }
 
-static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
+static int w83627ehf_detect(struct i2c_adapter *adapter)
 {
        struct i2c_client *client;
        struct w83627ehf_data *data;
        int i, err = 0;
 
-       if (!i2c_is_isa_adapter(adapter))
-               return 0;
-
        if (!request_region(address, REGION_LENGTH, w83627ehf_driver.name)) {
                err = -EBUSY;
                goto exit;
@@ -720,6 +718,12 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
                data->has_fan |= (1 << 4);
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&client->dev, &dev_attr_fan1_input);
        device_create_file(&client->dev, &dev_attr_fan1_min);
        device_create_file(&client->dev, &dev_attr_fan1_div);
@@ -753,6 +757,8 @@ static int w83627ehf_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(client);
 exit_free:
        kfree(data);
 exit_release:
@@ -761,24 +767,17 @@ exit:
        return err;
 }
 
-static int w83627ehf_attach_adapter(struct i2c_adapter *adapter)
-{
-       if (!(adapter->class & I2C_CLASS_HWMON))
-               return 0;
-       return i2c_detect(adapter, &addr_data, w83627ehf_detect);
-}
-
 static int w83627ehf_detach_client(struct i2c_client *client)
 {
+       struct w83627ehf_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
        release_region(client->addr, REGION_LENGTH);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -786,12 +785,11 @@ static int w83627ehf_detach_client(struct i2c_client *client)
 static struct i2c_driver w83627ehf_driver = {
        .owner          = THIS_MODULE,
        .name           = "w83627ehf",
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = w83627ehf_attach_adapter,
+       .attach_adapter = w83627ehf_detect,
        .detach_client  = w83627ehf_detach_client,
 };
 
-static int __init w83627ehf_find(int sioaddr, int *address)
+static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
 {
        u16 val;
 
@@ -809,8 +807,8 @@ static int __init w83627ehf_find(int sioaddr, int *address)
        superio_select(W83627EHF_LD_HWM);
        val = (superio_inb(SIO_REG_ADDR) << 8)
            | superio_inb(SIO_REG_ADDR + 1);
-       *address = val & ~(REGION_LENGTH - 1);
-       if (*address == 0) {
+       *addr = val & ~(REGION_LENGTH - 1);
+       if (*addr == 0) {
                superio_exit();
                return -ENODEV;
        }
@@ -826,16 +824,16 @@ static int __init w83627ehf_find(int sioaddr, int *address)
 
 static int __init sensors_w83627ehf_init(void)
 {
-       if (w83627ehf_find(0x2e, &normal_isa[0])
-        && w83627ehf_find(0x4e, &normal_isa[0]))
+       if (w83627ehf_find(0x2e, &address)
+        && w83627ehf_find(0x4e, &address))
                return -ENODEV;
 
-       return i2c_add_driver(&w83627ehf_driver);
+       return i2c_isa_add_driver(&w83627ehf_driver);
 }
 
 static void __exit sensors_w83627ehf_exit(void)
 {
-       i2c_del_driver(&w83627ehf_driver);
+       i2c_isa_del_driver(&w83627ehf_driver);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
index bd87a42e068ae4d6ac0fd1763d61b3c32b1bb5d7..02bd5c0239a2daba693652cdafb431efd75e77a4 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include "lm75.h"
 
@@ -56,12 +58,11 @@ module_param(force_i2c, byte, 0);
 MODULE_PARM_DESC(force_i2c,
                 "Initialize the i2c address of the sensors");
 
-/* Addresses to scan */
-static unsigned short normal_i2c[] = { I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0, I2C_CLIENT_ISA_END };
+/* The actual ISA address is read from Super-I/O configuration space */
+static unsigned short address;
 
 /* Insmod parameters */
-SENSORS_INSMOD_4(w83627hf, w83627thf, w83697hf, w83637hf);
+enum chips { any_chip, w83627hf, w83627thf, w83697hf, w83637hf };
 
 static int init = 1;
 module_param(init, bool, 0);
@@ -277,6 +278,7 @@ static inline u8 DIV_TO_REG(long val)
    dynamically allocated, at the same time when a new client is allocated. */
 struct w83627hf_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -314,9 +316,7 @@ struct w83627hf_data {
 };
 
 
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter);
-static int w83627hf_detect(struct i2c_adapter *adapter, int address,
-                         int kind);
+static int w83627hf_detect(struct i2c_adapter *adapter);
 static int w83627hf_detach_client(struct i2c_client *client);
 
 static int w83627hf_read_value(struct i2c_client *client, u16 register);
@@ -328,9 +328,7 @@ static void w83627hf_init_client(struct i2c_client *client);
 static struct i2c_driver w83627hf_driver = {
        .owner          = THIS_MODULE,
        .name           = "w83627hf",
-       .id             = I2C_DRIVERID_W83627HF,
-       .flags          = I2C_DF_NOTIFY,
-       .attach_adapter = w83627hf_attach_adapter,
+       .attach_adapter = w83627hf_detect,
        .detach_client  = w83627hf_detach_client,
 };
 
@@ -959,16 +957,7 @@ device_create_file(&client->dev, &dev_attr_temp##offset##_type); \
 } while (0)
 
 
-/* This function is called when:
-     * w83627hf_driver is inserted (when this module is loaded), for each
-       available adapter
-     * when a new adapter is inserted (and w83627hf_driver is still present) */
-static int w83627hf_attach_adapter(struct i2c_adapter *adapter)
-{
-       return i2c_detect(adapter, &addr_data, w83627hf_detect);
-}
-
-static int w83627hf_find(int sioaddr, int *address)
+static int __init w83627hf_find(int sioaddr, unsigned short *addr)
 {
        u16 val;
 
@@ -988,32 +977,24 @@ static int w83627hf_find(int sioaddr, int *address)
        superio_select(W83627HF_LD_HWM);
        val = (superio_inb(WINB_BASE_REG) << 8) |
               superio_inb(WINB_BASE_REG + 1);
-       *address = val & ~(WINB_EXTENT - 1);
-       if (*address == 0 && force_addr == 0) {
+       *addr = val & ~(WINB_EXTENT - 1);
+       if (*addr == 0 && force_addr == 0) {
                superio_exit();
                return -ENODEV;
        }
-       if (force_addr)
-               *address = force_addr;  /* so detect will get called */
 
        superio_exit();
        return 0;
 }
 
-int w83627hf_detect(struct i2c_adapter *adapter, int address,
-                  int kind)
+static int w83627hf_detect(struct i2c_adapter *adapter)
 {
-       int val;
+       int val, kind;
        struct i2c_client *new_client;
        struct w83627hf_data *data;
        int err = 0;
        const char *client_name = "";
 
-       if (!i2c_is_isa_adapter(adapter)) {
-               err = -ENODEV;
-               goto ERROR0;
-       }
-
        if(force_addr)
                address = force_addr & ~(WINB_EXTENT - 1);
 
@@ -1102,6 +1083,12 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
        data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        device_create_file_in(new_client, 0);
        if (kind != w83697hf)
                device_create_file_in(new_client, 1);
@@ -1152,6 +1139,8 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
 
        return 0;
 
+      ERROR3:
+       i2c_detach_client(new_client);
       ERROR2:
        kfree(data);
       ERROR1:
@@ -1162,16 +1151,16 @@ int w83627hf_detect(struct i2c_adapter *adapter, int address,
 
 static int w83627hf_detach_client(struct i2c_client *client)
 {
+       struct w83627hf_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                      "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        release_region(client->addr, WINB_EXTENT);
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -1327,7 +1316,7 @@ static void w83627hf_init_client(struct i2c_client *client)
                data->vrm = (data->vrm_ovt & 0x01) ? 90 : 82;
        } else {
                /* Convert VID to voltage based on default VRM */
-               data->vrm = i2c_which_vrm();
+               data->vrm = vid_which_vrm();
        }
 
        tmp = w83627hf_read_value(client, W83781D_REG_SCFG1);
@@ -1485,20 +1474,17 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
 
 static int __init sensors_w83627hf_init(void)
 {
-       int addr;
-
-       if (w83627hf_find(0x2e, &addr)
-        && w83627hf_find(0x4e, &addr)) {
+       if (w83627hf_find(0x2e, &address)
+        && w83627hf_find(0x4e, &address)) {
                return -ENODEV;
        }
-       normal_isa[0] = addr;
 
-       return i2c_add_driver(&w83627hf_driver);
+       return i2c_isa_add_driver(&w83627hf_driver);
 }
 
 static void __exit sensors_w83627hf_exit(void)
 {
-       i2c_del_driver(&w83627hf_driver);
+       i2c_isa_del_driver(&w83627hf_driver);
 }
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
index 0bb131ce09ebc931fdebf415c75c6c6f255f7e11..4c43337ca780abe0cde6ee81590de98b3edfbff8 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
-#include <linux/i2c-vid.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 #include "lm75.h"
 
 static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
                                        0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
                                        0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
+I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
                    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -218,6 +220,7 @@ DIV_TO_REG(long val, enum chips type)
    allocated. */
 struct w83781d_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -255,6 +258,7 @@ struct w83781d_data {
 };
 
 static int w83781d_attach_adapter(struct i2c_adapter *adapter);
+static int w83781d_isa_attach_adapter(struct i2c_adapter *adapter);
 static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
 static int w83781d_detach_client(struct i2c_client *client);
 
@@ -273,6 +277,14 @@ static struct i2c_driver w83781d_driver = {
        .detach_client = w83781d_detach_client,
 };
 
+static struct i2c_driver w83781d_isa_driver = {
+       .owner = THIS_MODULE,
+       .name = "w83781d-isa",
+       .attach_adapter = w83781d_isa_attach_adapter,
+       .detach_client = w83781d_detach_client,
+};
+
+
 /* following are the sysfs callback functions */
 #define show_in_reg(reg) \
 static ssize_t show_##reg (struct device *dev, char *buf, int nr) \
@@ -856,7 +868,13 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, w83781d_detect);
+       return i2c_probe(adapter, &addr_data, w83781d_detect);
+}
+
+static int
+w83781d_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+       return w83781d_detect(adapter, isa_address, -1);
 }
 
 /* Assumes that adapter is of I2C, not ISA variety.
@@ -961,10 +979,10 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
 ERROR_SC_3:
        i2c_detach_client(data->lm75[0]);
 ERROR_SC_2:
-       if (NULL != data->lm75[1])
+       if (data->lm75[1])
                kfree(data->lm75[1]);
 ERROR_SC_1:
-       if (NULL != data->lm75[0])
+       if (data->lm75[0])
                kfree(data->lm75[0]);
 ERROR_SC_0:
        return err;
@@ -999,7 +1017,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        
        if (is_isa)
                if (!request_region(address, W83781D_EXTENT,
-                                   w83781d_driver.name)) {
+                                   w83781d_isa_driver.name)) {
                        dev_dbg(&adapter->dev, "Request of region "
                                "0x%x-0x%x for w83781d failed\n", address,
                                address + W83781D_EXTENT - 1);
@@ -1057,7 +1075,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
        new_client->addr = address;
        init_MUTEX(&data->lock);
        new_client->adapter = adapter;
-       new_client->driver = &w83781d_driver;
+       new_client->driver = is_isa ? &w83781d_isa_driver : &w83781d_driver;
        new_client->flags = 0;
 
        /* Now, we do the remaining detection. */
@@ -1189,6 +1207,12 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                        data->pwmenable[i] = 1;
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR4;
+       }
+
        device_create_file_in(new_client, 0);
        if (kind != w83783s)
                device_create_file_in(new_client, 1);
@@ -1241,6 +1265,15 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+ERROR4:
+       if (data->lm75[1]) {
+               i2c_detach_client(data->lm75[1]);
+               kfree(data->lm75[1]);
+       }
+       if (data->lm75[0]) {
+               i2c_detach_client(data->lm75[0]);
+               kfree(data->lm75[0]);
+       }
 ERROR3:
        i2c_detach_client(new_client);
 ERROR2:
@@ -1255,24 +1288,26 @@ ERROR0:
 static int
 w83781d_detach_client(struct i2c_client *client)
 {
+       struct w83781d_data *data = i2c_get_clientdata(client);
        int err;
 
+       /* main client */
+       if (data)
+               hwmon_device_unregister(data->class_dev);
+
        if (i2c_is_isa_client(client))
                release_region(client->addr, W83781D_EXTENT);
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                      "Client deregistration failed, client not detached.\n");
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       if (i2c_get_clientdata(client)==NULL) {
-               /* subclients */
+       /* main client */
+       if (data)
+               kfree(data);
+
+       /* subclient */
+       else
                kfree(client);
-       } else {
-               /* main client */
-               kfree(i2c_get_clientdata(client));
-       }
 
        return 0;
 }
@@ -1443,7 +1478,7 @@ w83781d_init_client(struct i2c_client *client)
                w83781d_write_value(client, W83781D_REG_BEEP_INTS2, 0);
        }
 
-       data->vrm = i2c_which_vrm();
+       data->vrm = vid_which_vrm();
 
        if ((type != w83781d) && (type != as99127f)) {
                tmp = w83781d_read_value(client, W83781D_REG_SCFG1);
@@ -1613,12 +1648,25 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
 static int __init
 sensors_w83781d_init(void)
 {
-       return i2c_add_driver(&w83781d_driver);
+       int res;
+
+       res = i2c_add_driver(&w83781d_driver);
+       if (res)
+               return res;
+
+       res = i2c_isa_add_driver(&w83781d_isa_driver);
+       if (res) {
+               i2c_del_driver(&w83781d_driver);
+               return res;
+       }
+
+       return 0;
 }
 
 static void __exit
 sensors_w83781d_exit(void)
 {
+       i2c_isa_del_driver(&w83781d_isa_driver);
        i2c_del_driver(&w83781d_driver);
 }
 
diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c
new file mode 100644 (file)
index 0000000..ba0c280
--- /dev/null
@@ -0,0 +1,1649 @@
+/*
+    w83792d.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+    Copyright (C) 2004, 2005 Winbond Electronics Corp.
+                        Chunhao Huang <DZShen@Winbond.com.tw>,
+                        Rudolf Marek <r.marek@sh.cvut.cz>
+
+    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., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+    Note:
+    1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver.
+    2. This driver is only for Winbond W83792D C version device, there
+       are also some motherboards with B version W83792D device. The
+       calculation method to in6-in7(measured value, limits) is a little
+       different between C and B version. C or B version can be identified
+       by CR[0x49h].
+*/
+
+/*
+    Supports following chips:
+
+    Chip       #vin    #fanin  #pwm    #temp   wchipid vendid  i2c     ISA
+    w83792d    9       7       7       3       0x7a    0x5ca3  yes     no
+*/
+
+#include <linux/config.h>
+#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 to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(w83792d);
+I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
+                       "{bus, clientaddr, subclientaddr1, subclientaddr2}");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to one to force chip initialization");
+
+/* The W83792D registers */
+static const u8 W83792D_REG_IN[9] = {
+       0x20,   /* Vcore A in DataSheet */
+       0x21,   /* Vcore B in DataSheet */
+       0x22,   /* VIN0 in DataSheet */
+       0x23,   /* VIN1 in DataSheet */
+       0x24,   /* VIN2 in DataSheet */
+       0x25,   /* VIN3 in DataSheet */
+       0x26,   /* 5VCC in DataSheet */
+       0xB0,   /* 5VSB in DataSheet */
+       0xB1    /* VBAT in DataSheet */
+};
+#define W83792D_REG_LOW_BITS1 0x3E  /* Low Bits I in DataSheet */
+#define W83792D_REG_LOW_BITS2 0x3F  /* Low Bits II in DataSheet */
+static const u8 W83792D_REG_IN_MAX[9] = {
+       0x2B,   /* Vcore A High Limit in DataSheet */
+       0x2D,   /* Vcore B High Limit in DataSheet */
+       0x2F,   /* VIN0 High Limit in DataSheet */
+       0x31,   /* VIN1 High Limit in DataSheet */
+       0x33,   /* VIN2 High Limit in DataSheet */
+       0x35,   /* VIN3 High Limit in DataSheet */
+       0x37,   /* 5VCC High Limit in DataSheet */
+       0xB4,   /* 5VSB High Limit in DataSheet */
+       0xB6    /* VBAT High Limit in DataSheet */
+};
+static const u8 W83792D_REG_IN_MIN[9] = {
+       0x2C,   /* Vcore A Low Limit in DataSheet */
+       0x2E,   /* Vcore B Low Limit in DataSheet */
+       0x30,   /* VIN0 Low Limit in DataSheet */
+       0x32,   /* VIN1 Low Limit in DataSheet */
+       0x34,   /* VIN2 Low Limit in DataSheet */
+       0x36,   /* VIN3 Low Limit in DataSheet */
+       0x38,   /* 5VCC Low Limit in DataSheet */
+       0xB5,   /* 5VSB Low Limit in DataSheet */
+       0xB7    /* VBAT Low Limit in DataSheet */
+};
+static const u8 W83792D_REG_FAN[7] = {
+       0x28,   /* FAN 1 Count in DataSheet */
+       0x29,   /* FAN 2 Count in DataSheet */
+       0x2A,   /* FAN 3 Count in DataSheet */
+       0xB8,   /* FAN 4 Count in DataSheet */
+       0xB9,   /* FAN 5 Count in DataSheet */
+       0xBA,   /* FAN 6 Count in DataSheet */
+       0xBE    /* FAN 7 Count in DataSheet */
+};
+static const u8 W83792D_REG_FAN_MIN[7] = {
+       0x3B,   /* FAN 1 Count Low Limit in DataSheet */
+       0x3C,   /* FAN 2 Count Low Limit in DataSheet */
+       0x3D,   /* FAN 3 Count Low Limit in DataSheet */
+       0xBB,   /* FAN 4 Count Low Limit in DataSheet */
+       0xBC,   /* FAN 5 Count Low Limit in DataSheet */
+       0xBD,   /* FAN 6 Count Low Limit in DataSheet */
+       0xBF    /* FAN 7 Count Low Limit in DataSheet */
+};
+#define W83792D_REG_FAN_CFG 0x84       /* FAN Configuration in DataSheet */
+static const u8 W83792D_REG_FAN_DIV[4] = {
+       0x47,   /* contains FAN2 and FAN1 Divisor */
+       0x5B,   /* contains FAN4 and FAN3 Divisor */
+       0x5C,   /* contains FAN6 and FAN5 Divisor */
+       0x9E    /* contains FAN7 Divisor. */
+};
+static const u8 W83792D_REG_PWM[7] = {
+       0x81,   /* FAN 1 Duty Cycle, be used to control */
+       0x83,   /* FAN 2 Duty Cycle, be used to control */
+       0x94,   /* FAN 3 Duty Cycle, be used to control */
+       0xA3,   /* FAN 4 Duty Cycle, be used to control */
+       0xA4,   /* FAN 5 Duty Cycle, be used to control */
+       0xA5,   /* FAN 6 Duty Cycle, be used to control */
+       0xA6    /* FAN 7 Duty Cycle, be used to control */
+};
+#define W83792D_REG_BANK               0x4E
+#define W83792D_REG_TEMP2_CONFIG       0xC2
+#define W83792D_REG_TEMP3_CONFIG       0xCA
+
+static const u8 W83792D_REG_TEMP1[3] = {
+       0x27,   /* TEMP 1 in DataSheet */
+       0x39,   /* TEMP 1 Over in DataSheet */
+       0x3A,   /* TEMP 1 Hyst in DataSheet */
+};
+
+static const u8 W83792D_REG_TEMP_ADD[2][6] = {
+       { 0xC0,         /* TEMP 2 in DataSheet */
+         0xC1,         /* TEMP 2(0.5 deg) in DataSheet */
+         0xC5,         /* TEMP 2 Over High part in DataSheet */
+         0xC6,         /* TEMP 2 Over Low part in DataSheet */
+         0xC3,         /* TEMP 2 Thyst High part in DataSheet */
+         0xC4 },       /* TEMP 2 Thyst Low part in DataSheet */
+       { 0xC8,         /* TEMP 3 in DataSheet */
+         0xC9,         /* TEMP 3(0.5 deg) in DataSheet */
+         0xCD,         /* TEMP 3 Over High part in DataSheet */
+         0xCE,         /* TEMP 3 Over Low part in DataSheet */
+         0xCB,         /* TEMP 3 Thyst High part in DataSheet */
+         0xCC }        /* TEMP 3 Thyst Low part in DataSheet */
+};
+
+static const u8 W83792D_REG_THERMAL[3] = {
+       0x85,   /* SmartFanI: Fan1 target value */
+       0x86,   /* SmartFanI: Fan2 target value */
+       0x96    /* SmartFanI: Fan3 target value */
+};
+
+static const u8 W83792D_REG_TOLERANCE[3] = {
+       0x87,   /* (bit3-0)SmartFan Fan1 tolerance */
+       0x87,   /* (bit7-4)SmartFan Fan2 tolerance */
+       0x97    /* (bit3-0)SmartFan Fan3 tolerance */
+};
+
+static const u8 W83792D_REG_POINTS[3][4] = {
+       { 0x85,         /* SmartFanII: Fan1 temp point 1 */
+         0xE3,         /* SmartFanII: Fan1 temp point 2 */
+         0xE4,         /* SmartFanII: Fan1 temp point 3 */
+         0xE5 },       /* SmartFanII: Fan1 temp point 4 */
+       { 0x86,         /* SmartFanII: Fan2 temp point 1 */
+         0xE6,         /* SmartFanII: Fan2 temp point 2 */
+         0xE7,         /* SmartFanII: Fan2 temp point 3 */
+         0xE8 },       /* SmartFanII: Fan2 temp point 4 */
+       { 0x96,         /* SmartFanII: Fan3 temp point 1 */
+         0xE9,         /* SmartFanII: Fan3 temp point 2 */
+         0xEA,         /* SmartFanII: Fan3 temp point 3 */
+         0xEB }        /* SmartFanII: Fan3 temp point 4 */
+};
+
+static const u8 W83792D_REG_LEVELS[3][4] = {
+       { 0x88,         /* (bit3-0) SmartFanII: Fan1 Non-Stop */
+         0x88,         /* (bit7-4) SmartFanII: Fan1 Level 1 */
+         0xE0,         /* (bit7-4) SmartFanII: Fan1 Level 2 */
+         0xE0 },       /* (bit3-0) SmartFanII: Fan1 Level 3 */
+       { 0x89,         /* (bit3-0) SmartFanII: Fan2 Non-Stop */
+         0x89,         /* (bit7-4) SmartFanII: Fan2 Level 1 */
+         0xE1,         /* (bit7-4) SmartFanII: Fan2 Level 2 */
+         0xE1 },       /* (bit3-0) SmartFanII: Fan2 Level 3 */
+       { 0x98,         /* (bit3-0) SmartFanII: Fan3 Non-Stop */
+         0x98,         /* (bit7-4) SmartFanII: Fan3 Level 1 */
+         0xE2,         /* (bit7-4) SmartFanII: Fan3 Level 2 */
+         0xE2 }        /* (bit3-0) SmartFanII: Fan3 Level 3 */
+};
+
+#define W83792D_REG_CONFIG             0x40
+#define W83792D_REG_VID_FANDIV         0x47
+#define W83792D_REG_CHIPID             0x49
+#define W83792D_REG_WCHIPID            0x58
+#define W83792D_REG_CHIPMAN            0x4F
+#define W83792D_REG_PIN                        0x4B
+#define W83792D_REG_I2C_SUBADDR                0x4A
+
+#define W83792D_REG_ALARM1 0xA9                /* realtime status register1 */
+#define W83792D_REG_ALARM2 0xAA                /* realtime status register2 */
+#define W83792D_REG_ALARM3 0xAB                /* realtime status register3 */
+#define W83792D_REG_CHASSIS 0x42       /* Bit 5: Case Open status bit */
+#define W83792D_REG_CHASSIS_CLR 0x44   /* Bit 7: Case Open CLR_CHS/Reset bit */
+
+/* control in0/in1 's limit modifiability */
+#define W83792D_REG_VID_IN_B           0x17
+
+#define W83792D_REG_VBAT               0x5D
+#define W83792D_REG_I2C_ADDR           0x48
+
+/* Conversions. Rounding and limit checking is only done on the TO_REG
+   variants. Note that you should be a bit careful with which arguments
+   these macros are called: arguments may be evaluated more than once.
+   Fixing this is just not worth it. */
+#define IN_FROM_REG(nr,val) (((nr)<=1)?(val*2): \
+                               ((((nr)==6)||((nr)==7))?(val*6):(val*4)))
+#define IN_TO_REG(nr,val) (((nr)<=1)?(val/2): \
+                               ((((nr)==6)||((nr)==7))?(val/6):(val/4)))
+
+static inline u8
+FAN_TO_REG(long rpm, int div)
+{
+       if (rpm == 0)
+               return 255;
+       rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+       return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
+}
+
+#define FAN_FROM_REG(val,div)  ((val) == 0   ? -1 : \
+                               ((val) == 255 ? 0 : \
+                                               1350000 / ((val) * (div))))
+
+/* for temp1 */
+#define TEMP1_TO_REG(val)      (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+                                       : (val)) / 1000, 0, 0xff))
+#define TEMP1_FROM_REG(val)    (((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
+/* for temp2 and temp3, because they need addtional resolution */
+#define TEMP_ADD_FROM_REG(val1, val2) \
+       ((((val1) & 0x80 ? (val1)-0x100 \
+               : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0))
+#define TEMP_ADD_TO_REG_HIGH(val) \
+       (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
+                       : (val)) / 1000, 0, 0xff))
+#define TEMP_ADD_TO_REG_LOW(val)       ((val%1000) ? 0x80 : 0x00)
+
+#define PWM_FROM_REG(val)              (val)
+#define PWM_TO_REG(val)                        (SENSORS_LIMIT((val),0,255))
+#define DIV_FROM_REG(val)              (1 << (val))
+
+static inline u8
+DIV_TO_REG(long val)
+{
+       int i;
+       val = SENSORS_LIMIT(val, 1, 128) >> 1;
+       for (i = 0; i < 6; i++) {
+               if (val == 0)
+                       break;
+               val >>= 1;
+       }
+       return ((u8) i);
+}
+
+struct w83792d_data {
+       struct i2c_client client;
+       struct class_device *class_dev;
+       struct semaphore lock;
+       enum chips type;
+
+       struct semaphore update_lock;
+       char valid;             /* !=0 if following fields are valid */
+       unsigned long last_updated;     /* In jiffies */
+
+       /* array of 2 pointers to subclients */
+       struct i2c_client *lm75[2];
+
+       u8 in[9];               /* Register value */
+       u8 in_max[9];           /* Register value */
+       u8 in_min[9];           /* Register value */
+       u8 low_bits[2];         /* Additional resolution to voltage in0-6 */
+       u8 fan[7];              /* Register value */
+       u8 fan_min[7];          /* Register value */
+       u8 temp1[3];            /* current, over, thyst */
+       u8 temp_add[2][6];      /* Register value */
+       u8 fan_div[7];          /* Register encoding, shifted right */
+       u8 pwm[7];              /* We only consider the first 3 set of pwm,
+                                  although 792 chip has 7 set of pwm. */
+       u8 pwmenable[3];
+       u8 pwm_mode[7];         /* indicates PWM or DC mode: 1->PWM; 0->DC */
+       u32 alarms;             /* realtime status register encoding,combined */
+       u8 chassis;             /* Chassis status */
+       u8 chassis_clear;       /* CLR_CHS, clear chassis intrusion detection */
+       u8 thermal_cruise[3];   /* Smart FanI: Fan1,2,3 target value */
+       u8 tolerance[3];        /* Fan1,2,3 tolerance(Smart Fan I/II) */
+       u8 sf2_points[3][4];    /* Smart FanII: Fan1,2,3 temperature points */
+       u8 sf2_levels[3][4];    /* Smart FanII: Fan1,2,3 duty cycle levels */
+};
+
+static int w83792d_attach_adapter(struct i2c_adapter *adapter);
+static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
+static int w83792d_detach_client(struct i2c_client *client);
+
+static int w83792d_read_value(struct i2c_client *client, u8 register);
+static int w83792d_write_value(struct i2c_client *client, u8 register,
+                               u8 value);
+static struct w83792d_data *w83792d_update_device(struct device *dev);
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev);
+#endif
+
+static void w83792d_init_client(struct i2c_client *client);
+
+static struct i2c_driver w83792d_driver = {
+       .owner = THIS_MODULE,
+       .name = "w83792d",
+       .flags = I2C_DF_NOTIFY,
+       .attach_adapter = w83792d_attach_adapter,
+       .detach_client = w83792d_detach_client,
+};
+
+static long in_count_from_reg(int nr, struct w83792d_data *data)
+{
+       u16 vol_count = data->in[nr];
+       u16 low_bits = 0;
+       vol_count = (vol_count << 2);
+       switch (nr)
+       {
+       case 0:  /* vin0 */
+               low_bits = (data->low_bits[0]) & 0x03;
+               break;
+       case 1:  /* vin1 */
+               low_bits = ((data->low_bits[0]) & 0x0c) >> 2;
+               break;
+       case 2:  /* vin2 */
+               low_bits = ((data->low_bits[0]) & 0x30) >> 4;
+               break;
+       case 3:  /* vin3 */
+               low_bits = ((data->low_bits[0]) & 0xc0) >> 6;
+               break;
+       case 4:  /* vin4 */
+               low_bits = (data->low_bits[1]) & 0x03;
+               break;
+       case 5:  /* vin5 */
+               low_bits = ((data->low_bits[1]) & 0x0c) >> 2;
+               break;
+       case 6:  /* vin6 */
+               low_bits = ((data->low_bits[1]) & 0x30) >> 4;
+       default:
+               break;
+       }
+       vol_count = vol_count | low_bits;
+       return vol_count;
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf,"%ld\n", IN_FROM_REG(nr,(in_count_from_reg(nr, data))));
+}
+
+#define show_in_reg(reg) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+                       char *buf) \
+{ \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       struct w83792d_data *data = w83792d_update_device(dev); \
+       return sprintf(buf,"%ld\n", (long)(IN_FROM_REG(nr, (data->reg[nr])*4))); \
+}
+
+show_in_reg(in_min);
+show_in_reg(in_max);
+
+#define store_in_reg(REG, reg) \
+static ssize_t store_in_##reg (struct device *dev, \
+                               struct device_attribute *attr, \
+                               const char *buf, size_t count) \
+{ \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index; \
+       struct i2c_client *client = to_i2c_client(dev); \
+       struct w83792d_data *data = i2c_get_clientdata(client); \
+       u32 val; \
+        \
+       val = simple_strtoul(buf, NULL, 10); \
+       data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val)/4, 0, 255); \
+       w83792d_write_value(client, W83792D_REG_IN_##REG[nr], data->in_##reg[nr]); \
+        \
+       return count; \
+}
+store_in_reg(MIN, min);
+store_in_reg(MAX, max);
+
+#define sysfs_in_reg(offset) \
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \
+                               NULL, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+                               show_in_min, store_in_min, offset); \
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+                               show_in_max, store_in_max, offset);
+
+sysfs_in_reg(0);
+sysfs_in_reg(1);
+sysfs_in_reg(2);
+sysfs_in_reg(3);
+sysfs_in_reg(4);
+sysfs_in_reg(5);
+sysfs_in_reg(6);
+sysfs_in_reg(7);
+sysfs_in_reg(8);
+
+#define device_create_file_in(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_in##offset##_min.dev_attr); \
+} while (0)
+
+#define show_fan_reg(reg) \
+static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
+                       char *buf) \
+{ \
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+       int nr = sensor_attr->index - 1; \
+       struct w83792d_data *data = w83792d_update_device(dev); \
+       return sprintf(buf,"%d\n", \
+               FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \
+}
+
+show_fan_reg(fan);
+show_fan_reg(fan_min);
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+
+       val = simple_strtoul(buf, NULL, 10);
+       data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
+       w83792d_write_value(client, W83792D_REG_FAN_MIN[nr],
+                               data->fan_min[nr]);
+
+       return count;
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1]));
+}
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t
+store_fan_div(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       unsigned long min;
+       /*u8 reg;*/
+       u8 fan_div_reg = 0;
+       u8 tmp_fan_div;
+
+       /* Save fan_min */
+       min = FAN_FROM_REG(data->fan_min[nr],
+                          DIV_FROM_REG(data->fan_div[nr]));
+
+       data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+       fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]);
+       fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8;
+       tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70)
+                                       : ((data->fan_div[nr]) & 0x07);
+       w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1],
+                                       fan_div_reg | tmp_fan_div);
+
+       /* Restore fan_min */
+       data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+       w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]);
+
+       return count;
+}
+
+#define sysfs_fan(offset) \
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \
+                               offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
+                               show_fan_div, store_fan_div, offset); \
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \
+                               show_fan_min, store_fan_min, offset);
+
+sysfs_fan(1);
+sysfs_fan(2);
+sysfs_fan(3);
+sysfs_fan(4);
+sysfs_fan(5);
+sysfs_fan(6);
+sysfs_fan(7);
+
+#define device_create_file_fan(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_div.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_fan##offset##_min.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature1, includes measured value and limits */
+
+static ssize_t show_temp1(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[nr]));
+}
+
+static ssize_t store_temp1(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       s32 val;
+
+       val = simple_strtol(buf, NULL, 10);
+
+       data->temp1[nr] = TEMP1_TO_REG(val);
+       w83792d_write_value(client, W83792D_REG_TEMP1[nr],
+               data->temp1[nr]);
+
+       return count;
+}
+
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1,
+                               store_temp1, 1);
+static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1,
+                               store_temp1, 2);
+
+#define device_create_file_temp1(client) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp1_max_hyst.dev_attr); \
+} while (0)
+
+
+/* read/write the temperature2-3, includes measured value and limits */
+
+static ssize_t show_temp23(struct device *dev, struct device_attribute *attr,
+                               char *buf)
+{
+       struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+       int nr = sensor_attr->nr;
+       int index = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf,"%ld\n",
+               (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index],
+                       data->temp_add[nr][index+1]));
+}
+
+static ssize_t store_temp23(struct device *dev, struct device_attribute *attr,
+                               const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+       int nr = sensor_attr->nr;
+       int index = sensor_attr->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       s32 val;
+
+       val = simple_strtol(buf, NULL, 10);
+
+       data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val);
+       data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val);
+       w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index],
+               data->temp_add[nr][index]);
+       w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1],
+               data->temp_add[nr][index+1]);
+
+       return count;
+}
+
+#define sysfs_temp23(name,idx) \
+static SENSOR_DEVICE_ATTR_2(name##_input, S_IRUGO, show_temp23, NULL, \
+                               idx, 0); \
+static SENSOR_DEVICE_ATTR_2(name##_max, S_IRUGO | S_IWUSR, \
+                               show_temp23, store_temp23, idx, 2); \
+static SENSOR_DEVICE_ATTR_2(name##_max_hyst, S_IRUGO | S_IWUSR, \
+                               show_temp23, store_temp23, idx, 4);
+
+sysfs_temp23(temp2,0)
+sysfs_temp23(temp3,1)
+
+#define device_create_file_temp_add(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_input.dev_attr); \
+device_create_file(&client->dev, &sensor_dev_attr_temp##offset##_max.dev_attr); \
+device_create_file(&client->dev, \
+&sensor_dev_attr_temp##offset##_max_hyst.dev_attr); \
+} while (0)
+
+
+/* get reatime status of all sensors items: voltage, temp, fan */
+static ssize_t
+show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%d\n", data->alarms);
+}
+
+static
+DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL);
+#define device_create_file_alarms(client) \
+device_create_file(&client->dev, &dev_attr_alarms);
+
+
+
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr-1]));
+}
+
+static ssize_t
+show_pwmenable(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       long pwm_enable_tmp = 1;
+
+       switch (data->pwmenable[nr]) {
+       case 0:
+               pwm_enable_tmp = 1; /* manual mode */
+               break;
+       case 1:
+               pwm_enable_tmp = 3; /*thermal cruise/Smart Fan I */
+               break;
+       case 2:
+               pwm_enable_tmp = 2; /* Smart Fan II */
+               break;
+       }
+
+       return sprintf(buf, "%ld\n", pwm_enable_tmp);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+
+       val = simple_strtoul(buf, NULL, 10);
+       data->pwm[nr] = PWM_TO_REG(val);
+       w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]);
+
+       return count;
+}
+
+static ssize_t
+store_pwmenable(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp;
+
+       val = simple_strtoul(buf, NULL, 10);
+       switch (val) {
+       case 1:
+               data->pwmenable[nr] = 0; /* manual mode */
+               break;
+       case 2:
+               data->pwmenable[nr] = 2; /* Smart Fan II */
+               break;
+       case 3:
+               data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */
+               break;
+       default:
+               return -EINVAL;
+       }
+       cfg1_tmp = data->pwmenable[0];
+       cfg2_tmp = (data->pwmenable[1]) << 2;
+       cfg3_tmp = (data->pwmenable[2]) << 4;
+       cfg4_tmp = w83792d_read_value(client,W83792D_REG_FAN_CFG) & 0xc0;
+       fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp;
+       w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp);
+
+       return count;
+}
+
+#define sysfs_pwm(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \
+                               show_pwm, store_pwm, offset); \
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \
+                               show_pwmenable, store_pwmenable, offset); \
+
+sysfs_pwm(1);
+sysfs_pwm(2);
+sysfs_pwm(3);
+
+
+#define device_create_file_pwm(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset.dev_attr); \
+} while (0)
+
+#define device_create_file_pwmenable(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_enable.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_pwm_mode(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%d\n", data->pwm_mode[nr-1]);
+}
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 pwm_mode_mask = 0;
+
+       val = simple_strtoul(buf, NULL, 10);
+       data->pwm_mode[nr] = SENSORS_LIMIT(val, 0, 1);
+       pwm_mode_mask = w83792d_read_value(client,
+               W83792D_REG_PWM[nr]) & 0x7f;
+       w83792d_write_value(client, W83792D_REG_PWM[nr],
+               ((data->pwm_mode[nr]) << 7) | pwm_mode_mask);
+
+       return count;
+}
+
+#define sysfs_pwm_mode(offset) \
+static SENSOR_DEVICE_ATTR(pwm##offset##_mode, S_IRUGO | S_IWUSR, \
+                               show_pwm_mode, store_pwm_mode, offset);
+
+sysfs_pwm_mode(1);
+sysfs_pwm_mode(2);
+sysfs_pwm_mode(3);
+
+#define device_create_file_pwm_mode(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_pwm##offset##_mode.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_regs_chassis(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%d\n", data->chassis);
+}
+
+static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL);
+
+#define device_create_file_chassis(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis); \
+} while (0)
+
+
+static ssize_t
+show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%d\n", data->chassis_clear);
+}
+
+static ssize_t
+store_chassis_clear(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 temp1 = 0, temp2 = 0;
+
+       val = simple_strtoul(buf, NULL, 10);
+
+       data->chassis_clear = SENSORS_LIMIT(val, 0 ,1);
+       temp1 = ((data->chassis_clear) << 7) & 0x80;
+       temp2 = w83792d_read_value(client,
+               W83792D_REG_CHASSIS_CLR) & 0x7f;
+       w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
+
+       return count;
+}
+
+static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR,
+               show_chassis_clear, store_chassis_clear);
+
+#define device_create_file_chassis_clear(client) \
+do { \
+device_create_file(&client->dev, &dev_attr_chassis_clear); \
+} while (0)
+
+
+
+/* For Smart Fan I / Thermal Cruise */
+static ssize_t
+show_thermal_cruise(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%ld\n", (long)data->thermal_cruise[nr-1]);
+}
+
+static ssize_t
+store_thermal_cruise(struct device *dev, struct device_attribute *attr,
+                       const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 target_tmp=0, target_mask=0;
+
+       val = simple_strtoul(buf, NULL, 10);
+       target_tmp = val;
+       target_tmp = target_tmp & 0x7f;
+       target_mask = w83792d_read_value(client, W83792D_REG_THERMAL[nr]) & 0x80;
+       data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255);
+       w83792d_write_value(client, W83792D_REG_THERMAL[nr],
+               (data->thermal_cruise[nr]) | target_mask);
+
+       return count;
+}
+
+#define sysfs_thermal_cruise(offset) \
+static SENSOR_DEVICE_ATTR(thermal_cruise##offset, S_IRUGO | S_IWUSR, \
+                       show_thermal_cruise, store_thermal_cruise, offset);
+
+sysfs_thermal_cruise(1);
+sysfs_thermal_cruise(2);
+sysfs_thermal_cruise(3);
+
+#define device_create_file_thermal_cruise(client, offset) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_thermal_cruise##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan I/Thermal Cruise and Smart Fan II */
+static ssize_t
+show_tolerance(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%ld\n", (long)data->tolerance[nr-1]);
+}
+
+static ssize_t
+store_tolerance(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+       int nr = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 tol_tmp, tol_mask;
+
+       val = simple_strtoul(buf, NULL, 10);
+       tol_mask = w83792d_read_value(client,
+               W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0);
+       tol_tmp = SENSORS_LIMIT(val, 0, 15);
+       tol_tmp &= 0x0f;
+       data->tolerance[nr] = tol_tmp;
+       if (nr == 1) {
+               tol_tmp <<= 4;
+       }
+       w83792d_write_value(client, W83792D_REG_TOLERANCE[nr],
+               tol_mask | tol_tmp);
+
+       return count;
+}
+
+#define sysfs_tolerance(offset) \
+static SENSOR_DEVICE_ATTR(tolerance##offset, S_IRUGO | S_IWUSR, \
+                               show_tolerance, store_tolerance, offset);
+
+sysfs_tolerance(1);
+sysfs_tolerance(2);
+sysfs_tolerance(3);
+
+#define device_create_file_tolerance(client, offset) \
+do { \
+device_create_file(&client->dev, &sensor_dev_attr_tolerance##offset.dev_attr); \
+} while (0)
+
+
+/* For Smart Fan II */
+static ssize_t
+show_sf2_point(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+       int nr = sensor_attr->nr;
+       int index = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]);
+}
+
+static ssize_t
+store_sf2_point(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+       int nr = sensor_attr->nr - 1;
+       int index = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 mask_tmp = 0;
+
+       val = simple_strtoul(buf, NULL, 10);
+       data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127);
+       mask_tmp = w83792d_read_value(client,
+                                       W83792D_REG_POINTS[index][nr]) & 0x80;
+       w83792d_write_value(client, W83792D_REG_POINTS[index][nr],
+               mask_tmp|data->sf2_points[index][nr]);
+
+       return count;
+}
+
+#define sysfs_sf2_point(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_point##offset##_fan##index, S_IRUGO | S_IWUSR, \
+                               show_sf2_point, store_sf2_point, offset, index);
+
+sysfs_sf2_point(1, 1); /* Fan1 */
+sysfs_sf2_point(2, 1); /* Fan1 */
+sysfs_sf2_point(3, 1); /* Fan1 */
+sysfs_sf2_point(4, 1); /* Fan1 */
+sysfs_sf2_point(1, 2); /* Fan2 */
+sysfs_sf2_point(2, 2); /* Fan2 */
+sysfs_sf2_point(3, 2); /* Fan2 */
+sysfs_sf2_point(4, 2); /* Fan2 */
+sysfs_sf2_point(1, 3); /* Fan3 */
+sysfs_sf2_point(2, 3); /* Fan3 */
+sysfs_sf2_point(3, 3); /* Fan3 */
+sysfs_sf2_point(4, 3); /* Fan3 */
+
+#define device_create_file_sf2_point(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_point##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+static ssize_t
+show_sf2_level(struct device *dev, struct device_attribute *attr,
+               char *buf)
+{
+       struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+       int nr = sensor_attr->nr;
+       int index = sensor_attr->index;
+       struct w83792d_data *data = w83792d_update_device(dev);
+       return sprintf(buf, "%d\n",
+                       (((data->sf2_levels[index-1][nr]) * 100) / 15));
+}
+
+static ssize_t
+store_sf2_level(struct device *dev, struct device_attribute *attr,
+               const char *buf, size_t count)
+{
+       struct sensor_device_attribute_2 *sensor_attr = to_sensor_dev_attr_2(attr);
+       int nr = sensor_attr->nr;
+       int index = sensor_attr->index - 1;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       u32 val;
+       u8 mask_tmp=0, level_tmp=0;
+
+       val = simple_strtoul(buf, NULL, 10);
+       data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15);
+       mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr])
+               & ((nr==3) ? 0xf0 : 0x0f);
+       if (nr==3) {
+               level_tmp = data->sf2_levels[index][nr];
+       } else {
+               level_tmp = data->sf2_levels[index][nr] << 4;
+       }
+       w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], level_tmp | mask_tmp);
+
+       return count;
+}
+
+#define sysfs_sf2_level(offset, index) \
+static SENSOR_DEVICE_ATTR_2(sf2_level##offset##_fan##index, S_IRUGO | S_IWUSR, \
+                               show_sf2_level, store_sf2_level, offset, index);
+
+sysfs_sf2_level(1, 1); /* Fan1 */
+sysfs_sf2_level(2, 1); /* Fan1 */
+sysfs_sf2_level(3, 1); /* Fan1 */
+sysfs_sf2_level(1, 2); /* Fan2 */
+sysfs_sf2_level(2, 2); /* Fan2 */
+sysfs_sf2_level(3, 2); /* Fan2 */
+sysfs_sf2_level(1, 3); /* Fan3 */
+sysfs_sf2_level(2, 3); /* Fan3 */
+sysfs_sf2_level(3, 3); /* Fan3 */
+
+#define device_create_file_sf2_level(client, offset, index) \
+do { \
+device_create_file(&client->dev, \
+&sensor_dev_attr_sf2_level##offset##_fan##index.dev_attr); \
+} while (0)
+
+
+/* This function is called when:
+     * w83792d_driver is inserted (when this module is loaded), for each
+       available adapter
+     * when a new adapter is inserted (and w83792d_driver is still present) */
+static int
+w83792d_attach_adapter(struct i2c_adapter *adapter)
+{
+       if (!(adapter->class & I2C_CLASS_HWMON))
+               return 0;
+       return i2c_probe(adapter, &addr_data, w83792d_detect);
+}
+
+
+static int
+w83792d_create_subclient(struct i2c_adapter *adapter,
+                               struct i2c_client *new_client, int addr,
+                               struct i2c_client **sub_cli)
+{
+       int err;
+       struct i2c_client *sub_client;
+
+       (*sub_cli) = sub_client = kmalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (!(sub_client)) {
+               return -ENOMEM;
+       }
+       memset(sub_client, 0x00, sizeof(struct i2c_client));
+       sub_client->addr = 0x48 + addr;
+       i2c_set_clientdata(sub_client, NULL);
+       sub_client->adapter = adapter;
+       sub_client->driver = &w83792d_driver;
+       sub_client->flags = 0;
+       strlcpy(sub_client->name, "w83792d subclient", I2C_NAME_SIZE);
+       if ((err = i2c_attach_client(sub_client))) {
+               dev_err(&new_client->dev, "subclient registration "
+                       "at address 0x%x failed\n", sub_client->addr);
+               kfree(sub_client);
+               return err;
+       }
+       return 0;
+}
+
+
+static int
+w83792d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
+               struct i2c_client *new_client)
+{
+       int i, id, err;
+       u8 val;
+       struct w83792d_data *data = i2c_get_clientdata(new_client);
+
+       id = i2c_adapter_id(adapter);
+       if (force_subclients[0] == id && force_subclients[1] == address) {
+               for (i = 2; i <= 3; i++) {
+                       if (force_subclients[i] < 0x48 ||
+                           force_subclients[i] > 0x4f) {
+                               dev_err(&new_client->dev, "invalid subclient "
+                                       "address %d; must be 0x48-0x4f\n",
+                                       force_subclients[i]);
+                               err = -ENODEV;
+                               goto ERROR_SC_0;
+                       }
+               }
+               w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR,
+                                       (force_subclients[2] & 0x07) |
+                                       ((force_subclients[3] & 0x07) << 4));
+       }
+
+       val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR);
+       if (!(val & 0x08)) {
+               err = w83792d_create_subclient(adapter, new_client, val & 0x7,
+                                               &data->lm75[0]);
+               if (err < 0)
+                       goto ERROR_SC_0;
+       }
+       if (!(val & 0x80)) {
+               if ((data->lm75[0] != NULL) &&
+                       ((val & 0x7) == ((val >> 4) & 0x7))) {
+                       dev_err(&new_client->dev, "duplicate addresses 0x%x, "
+                               "use force_subclient\n", data->lm75[0]->addr);
+                       err = -ENODEV;
+                       goto ERROR_SC_1;
+               }
+               err = w83792d_create_subclient(adapter, new_client,
+                                               (val >> 4) & 0x7, &data->lm75[1]);
+               if (err < 0)
+                       goto ERROR_SC_1;
+       }
+
+       return 0;
+
+/* Undo inits in case of errors */
+
+ERROR_SC_1:
+       if (data->lm75[0] != NULL) {
+               i2c_detach_client(data->lm75[0]);
+               kfree(data->lm75[0]);
+       }
+ERROR_SC_0:
+       return err;
+}
+
+
+static int
+w83792d_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+       int i = 0, val1 = 0, val2;
+       struct i2c_client *new_client;
+       struct w83792d_data *data;
+       int err = 0;
+       const char *client_name = "";
+
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+               goto ERROR0;
+       }
+
+       /* OK. For now, we presume we have a valid client. We now create the
+          client structure, even though we cannot fill it completely yet.
+          But it allows us to access w83792d_{read,write}_value. */
+
+       if (!(data = kmalloc(sizeof(struct w83792d_data), GFP_KERNEL))) {
+               err = -ENOMEM;
+               goto ERROR0;
+       }
+       memset(data, 0, sizeof(struct w83792d_data));
+
+       new_client = &data->client;
+       i2c_set_clientdata(new_client, data);
+       new_client->addr = address;
+       init_MUTEX(&data->lock);
+       new_client->adapter = adapter;
+       new_client->driver = &w83792d_driver;
+       new_client->flags = 0;
+
+       /* Now, we do the remaining detection. */
+
+       /* 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(new_client, W83792D_REG_CONFIG) & 0x80) {
+                       dev_warn(&new_client->dev, "Detection failed at step "
+                               "3\n");
+                       goto ERROR1;
+               }
+               val1 = w83792d_read_value(new_client, W83792D_REG_BANK);
+               val2 = w83792d_read_value(new_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))) {
+                               goto ERROR1;
+                       }
+               }
+               /* If Winbond chip, address of chip and W83792D_REG_I2C_ADDR
+                  should match */
+               if (w83792d_read_value(new_client,
+                                       W83792D_REG_I2C_ADDR) != address) {
+                       dev_warn(&new_client->dev, "Detection failed "
+                               "at step 5\n");
+                       goto ERROR1;
+               }
+       }
+
+       /* 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 */
+       w83792d_write_value(new_client,
+                           W83792D_REG_BANK,
+                           (w83792d_read_value(new_client,
+                               W83792D_REG_BANK) & 0x78) | 0x80);
+
+       /* Determine the chip type. */
+       if (kind <= 0) {
+               /* get vendor ID */
+               val2 = w83792d_read_value(new_client, W83792D_REG_CHIPMAN);
+               if (val2 != 0x5c) {  /* the vendor is NOT Winbond */
+                       goto ERROR1;
+               }
+               val1 = w83792d_read_value(new_client, W83792D_REG_WCHIPID);
+               if (val1 == 0x7a && address >= 0x2c) {
+                       kind = w83792d;
+               } else {
+                       if (kind == 0)
+                                       dev_warn(&new_client->dev,
+                                       "w83792d: Ignoring 'force' parameter for"
+                                       " unknown chip at adapter %d, address"
+                                       " 0x%02x\n", i2c_adapter_id(adapter),
+                                       address);
+                       goto ERROR1;
+               }
+       }
+
+       if (kind == w83792d) {
+               client_name = "w83792d";
+       } else {
+               dev_err(&new_client->dev, "w83792d: Internal error: unknown"
+                                         " kind (%d)?!?", kind);
+               goto ERROR1;
+       }
+
+       /* Fill in the remaining client fields and put into the global list */
+       strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+       data->type = kind;
+
+       data->valid = 0;
+       init_MUTEX(&data->update_lock);
+
+       /* Tell the I2C layer a new client has arrived */
+       if ((err = i2c_attach_client(new_client)))
+               goto ERROR1;
+
+       if ((err = w83792d_detect_subclients(adapter, address,
+                       kind, new_client)))
+               goto ERROR2;
+
+       /* Initialize the chip */
+       w83792d_init_client(new_client);
+
+       /* A few vars need to be filled upon startup */
+       for (i = 1; i <= 7; i++) {
+               data->fan_min[i - 1] = w83792d_read_value(new_client,
+                                       W83792D_REG_FAN_MIN[i]);
+       }
+
+       /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+       device_create_file_in(new_client, 0);
+       device_create_file_in(new_client, 1);
+       device_create_file_in(new_client, 2);
+       device_create_file_in(new_client, 3);
+       device_create_file_in(new_client, 4);
+       device_create_file_in(new_client, 5);
+       device_create_file_in(new_client, 6);
+       device_create_file_in(new_client, 7);
+       device_create_file_in(new_client, 8);
+
+       device_create_file_fan(new_client, 1);
+       device_create_file_fan(new_client, 2);
+       device_create_file_fan(new_client, 3);
+       device_create_file_fan(new_client, 4);
+       device_create_file_fan(new_client, 5);
+       device_create_file_fan(new_client, 6);
+       device_create_file_fan(new_client, 7);
+
+       device_create_file_temp1(new_client);           /* Temp1 */
+       device_create_file_temp_add(new_client, 2);     /* Temp2 */
+       device_create_file_temp_add(new_client, 3);     /* Temp3 */
+
+       device_create_file_alarms(new_client);
+
+       device_create_file_pwm(new_client, 1);
+       device_create_file_pwm(new_client, 2);
+       device_create_file_pwm(new_client, 3);
+
+       device_create_file_pwmenable(new_client, 1);
+       device_create_file_pwmenable(new_client, 2);
+       device_create_file_pwmenable(new_client, 3);
+
+       device_create_file_pwm_mode(new_client, 1);
+       device_create_file_pwm_mode(new_client, 2);
+       device_create_file_pwm_mode(new_client, 3);
+
+       device_create_file_chassis(new_client);
+       device_create_file_chassis_clear(new_client);
+
+       device_create_file_thermal_cruise(new_client, 1);
+       device_create_file_thermal_cruise(new_client, 2);
+       device_create_file_thermal_cruise(new_client, 3);
+
+       device_create_file_tolerance(new_client, 1);
+       device_create_file_tolerance(new_client, 2);
+       device_create_file_tolerance(new_client, 3);
+
+       device_create_file_sf2_point(new_client, 1, 1); /* Fan1 */
+       device_create_file_sf2_point(new_client, 2, 1); /* Fan1 */
+       device_create_file_sf2_point(new_client, 3, 1); /* Fan1 */
+       device_create_file_sf2_point(new_client, 4, 1); /* Fan1 */
+       device_create_file_sf2_point(new_client, 1, 2); /* Fan2 */
+       device_create_file_sf2_point(new_client, 2, 2); /* Fan2 */
+       device_create_file_sf2_point(new_client, 3, 2); /* Fan2 */
+       device_create_file_sf2_point(new_client, 4, 2); /* Fan2 */
+       device_create_file_sf2_point(new_client, 1, 3); /* Fan3 */
+       device_create_file_sf2_point(new_client, 2, 3); /* Fan3 */
+       device_create_file_sf2_point(new_client, 3, 3); /* Fan3 */
+       device_create_file_sf2_point(new_client, 4, 3); /* Fan3 */
+
+       device_create_file_sf2_level(new_client, 1, 1); /* Fan1 */
+       device_create_file_sf2_level(new_client, 2, 1); /* Fan1 */
+       device_create_file_sf2_level(new_client, 3, 1); /* Fan1 */
+       device_create_file_sf2_level(new_client, 1, 2); /* Fan2 */
+       device_create_file_sf2_level(new_client, 2, 2); /* Fan2 */
+       device_create_file_sf2_level(new_client, 3, 2); /* Fan2 */
+       device_create_file_sf2_level(new_client, 1, 3); /* Fan3 */
+       device_create_file_sf2_level(new_client, 2, 3); /* Fan3 */
+       device_create_file_sf2_level(new_client, 3, 3); /* Fan3 */
+
+       return 0;
+
+ERROR3:
+       if (data->lm75[0] != NULL) {
+               i2c_detach_client(data->lm75[0]);
+               kfree(data->lm75[0]);
+       }
+       if (data->lm75[1] != NULL) {
+               i2c_detach_client(data->lm75[1]);
+               kfree(data->lm75[1]);
+       }
+ERROR2:
+       i2c_detach_client(new_client);
+ERROR1:
+       kfree(data);
+ERROR0:
+       return err;
+}
+
+static int
+w83792d_detach_client(struct i2c_client *client)
+{
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       int err;
+
+       /* main client */
+       if (data)
+               hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
+               return err;
+
+       /* main client */
+       if (data)
+               kfree(data);
+       /* subclient */
+       else
+               kfree(client);
+
+       return 0;
+}
+
+/* The SMBus locks itself, usually, but nothing may access the Winbond between
+   bank switches. ISA access must always be locked explicitly!
+   We ignore the W83792D BUSY flag at this moment - it could lead to deadlocks,
+   would slow down the W83792D access and should not be necessary.
+   There are some ugly typecasts here, but the good news is - they should
+   nowhere else be necessary! */
+static int
+w83792d_read_value(struct i2c_client *client, u8 reg)
+{
+       int res=0;
+       res = i2c_smbus_read_byte_data(client, reg);
+
+       return res;
+}
+
+static int
+w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+{
+       i2c_smbus_write_byte_data(client, reg,  value);
+       return 0;
+}
+
+/* Called when we have found a new W83792D. It should set limits, etc. */
+static void
+w83792d_init_client(struct i2c_client *client)
+{
+       u8 temp2_cfg, temp3_cfg, vid_in_b;
+
+       if (init) {
+               w83792d_write_value(client, W83792D_REG_CONFIG, 0x80);
+       }
+       /* Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0):
+          W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of
+            vin0/vin1 can be modified by user;
+          W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of
+            vin0/vin1 auto-updated, can NOT be modified by user. */
+       vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B);
+       w83792d_write_value(client, W83792D_REG_VID_IN_B,
+                           vid_in_b & 0xbf);
+
+       temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP2_CONFIG);
+       temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP3_CONFIG);
+       w83792d_write_value(client, W83792D_REG_TEMP2_CONFIG,
+                               temp2_cfg & 0xe6);
+       w83792d_write_value(client, W83792D_REG_TEMP3_CONFIG,
+                               temp3_cfg & 0xe6);
+
+       /* Start monitoring */
+       w83792d_write_value(client, W83792D_REG_CONFIG,
+                           (w83792d_read_value(client,
+                                               W83792D_REG_CONFIG) & 0xf7)
+                           | 0x01);
+}
+
+static struct w83792d_data *w83792d_update_device(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83792d_data *data = i2c_get_clientdata(client);
+       int i, j;
+       u8 reg_array_tmp[4], pwm_array_tmp[7], reg_tmp;
+
+       down(&data->update_lock);
+
+       if (time_after
+           (jiffies - data->last_updated, (unsigned long) (HZ * 3))
+           || time_before(jiffies, data->last_updated) || !data->valid) {
+               dev_dbg(dev, "Starting device update\n");
+
+               /* Update the voltages measured value and limits */
+               for (i = 0; i < 9; i++) {
+                       data->in[i] = w83792d_read_value(client,
+                                               W83792D_REG_IN[i]);
+                       data->in_max[i] = w83792d_read_value(client,
+                                               W83792D_REG_IN_MAX[i]);
+                       data->in_min[i] = w83792d_read_value(client,
+                                               W83792D_REG_IN_MIN[i]);
+               }
+               data->low_bits[0] = w83792d_read_value(client,
+                                               W83792D_REG_LOW_BITS1);
+               data->low_bits[1] = w83792d_read_value(client,
+                                               W83792D_REG_LOW_BITS2);
+               for (i = 0; i < 7; i++) {
+                       /* Update the Fan measured value and limits */
+                       data->fan[i] = w83792d_read_value(client,
+                                               W83792D_REG_FAN[i]);
+                       data->fan_min[i] = w83792d_read_value(client,
+                                               W83792D_REG_FAN_MIN[i]);
+                       /* Update the PWM/DC Value and PWM/DC flag */
+                       pwm_array_tmp[i] = w83792d_read_value(client,
+                                               W83792D_REG_PWM[i]);
+                       data->pwm[i] = pwm_array_tmp[i] & 0x0f;
+                       data->pwm_mode[i] = (pwm_array_tmp[i] >> 7) & 0x01;
+               }
+
+               reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG);
+               data->pwmenable[0] = reg_tmp & 0x03;
+               data->pwmenable[1] = (reg_tmp>>2) & 0x03;
+               data->pwmenable[2] = (reg_tmp>>4) & 0x03;
+
+               for (i = 0; i < 3; i++) {
+                       data->temp1[i] = w83792d_read_value(client,
+                                                       W83792D_REG_TEMP1[i]);
+               }
+               for (i = 0; i < 2; i++) {
+                       for (j = 0; j < 6; j++) {
+                               data->temp_add[i][j] = w83792d_read_value(
+                                       client,W83792D_REG_TEMP_ADD[i][j]);
+                       }
+               }
+
+               /* Update the Fan Divisor */
+               for (i = 0; i < 4; i++) {
+                       reg_array_tmp[i] = w83792d_read_value(client,
+                                                       W83792D_REG_FAN_DIV[i]);
+               }
+               data->fan_div[0] = reg_array_tmp[0] & 0x07;
+               data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07;
+               data->fan_div[2] = reg_array_tmp[1] & 0x07;
+               data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07;
+               data->fan_div[4] = reg_array_tmp[2] & 0x07;
+               data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07;
+               data->fan_div[6] = reg_array_tmp[3] & 0x07;
+
+               /* Update the realtime status */
+               data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) +
+                       (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) +
+                       (w83792d_read_value(client, W83792D_REG_ALARM3) << 16);
+
+               /* Update CaseOpen status and it's CLR_CHS. */
+               data->chassis = (w83792d_read_value(client,
+                       W83792D_REG_CHASSIS) >> 5) & 0x01;
+               data->chassis_clear = (w83792d_read_value(client,
+                       W83792D_REG_CHASSIS_CLR) >> 7) & 0x01;
+
+               /* Update Thermal Cruise/Smart Fan I target value */
+               for (i = 0; i < 3; i++) {
+                       data->thermal_cruise[i] =
+                               w83792d_read_value(client,
+                               W83792D_REG_THERMAL[i]) & 0x7f;
+               }
+
+               /* Update Smart Fan I/II tolerance */
+               reg_tmp = w83792d_read_value(client, W83792D_REG_TOLERANCE[0]);
+               data->tolerance[0] = reg_tmp & 0x0f;
+               data->tolerance[1] = (reg_tmp >> 4) & 0x0f;
+               data->tolerance[2] = w83792d_read_value(client,
+                                       W83792D_REG_TOLERANCE[2]) & 0x0f;
+
+               /* Update Smart Fan II temperature points */
+               for (i = 0; i < 3; i++) {
+                       for (j = 0; j < 4; j++) {
+                               data->sf2_points[i][j] = w83792d_read_value(
+                                       client,W83792D_REG_POINTS[i][j]) & 0x7f;
+                       }
+               }
+
+               /* Update Smart Fan II duty cycle levels */
+               for (i = 0; i < 3; i++) {
+                       reg_tmp = w83792d_read_value(client,
+                                               W83792D_REG_LEVELS[i][0]);
+                       data->sf2_levels[i][0] = reg_tmp & 0x0f;
+                       data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f;
+                       reg_tmp = w83792d_read_value(client,
+                                               W83792D_REG_LEVELS[i][2]);
+                       data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f;
+                       data->sf2_levels[i][3] = reg_tmp & 0x0f;
+               }
+
+               data->last_updated = jiffies;
+               data->valid = 1;
+       }
+
+       up(&data->update_lock);
+
+#ifdef DEBUG
+       w83792d_print_debug(data, dev);
+#endif
+
+       return data;
+}
+
+#ifdef DEBUG
+static void w83792d_print_debug(struct w83792d_data *data, struct device *dev)
+{
+       int i=0, j=0;
+       dev_dbg(dev, "==========The following is the debug message...========\n");
+       dev_dbg(dev, "9 set of Voltages: =====>\n");
+       for (i=0; i<9; i++) {
+               dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]);
+               dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]);
+               dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]);
+       }
+       dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits[0]);
+       dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits[1]);
+       dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n");
+       for (i=0; i<7; i++) {
+               dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]);
+               dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]);
+               dev_dbg(dev, "pwm[%d]     is: 0x%x\n", i, data->pwm[i]);
+               dev_dbg(dev, "pwm_mode[%d] is: 0x%x\n", i, data->pwm_mode[i]);
+       }
+       dev_dbg(dev, "3 set of Temperatures: =====>\n");
+       for (i=0; i<3; i++) {
+               dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]);
+       }
+
+       for (i=0; i<2; i++) {
+               for (j=0; j<6; j++) {
+                       dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j,
+                                                       data->temp_add[i][j]);
+               }
+       }
+
+       for (i=0; i<7; i++) {
+               dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]);
+       }
+       dev_dbg(dev, "==========End of the debug message...==================\n");
+       dev_dbg(dev, "\n");
+}
+#endif
+
+static int __init
+sensors_w83792d_init(void)
+{
+       return i2c_add_driver(&w83792d_driver);
+}
+
+static void __exit
+sensors_w83792d_exit(void)
+{
+       i2c_del_driver(&w83792d_driver);
+}
+
+MODULE_AUTHOR("Chunhao Huang @ Winbond <DZShen@Winbond.com.tw>");
+MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_w83792d_init);
+module_exit(sensors_w83792d_exit);
+
index 4469d52aba4c6faefa0bc3047b379ad614eea6d3..133e34ab1d0af1a1ab0b965ca58fb59c554d6d11 100644 (file)
@@ -36,7 +36,8 @@
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/hwmon.h>
+#include <linux/err.h>
 
 /* How many retries on register read error */
 #define MAX_RETRIES    5
  */
 
 static unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END };
-static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
 
 /*
  * Insmod parameters
  */
 
-SENSORS_INSMOD_1(w83l785ts);
+I2C_CLIENT_INSMOD_1(w83l785ts);
 
 /*
  * The W83L785TS-S registers
@@ -105,6 +105,7 @@ static struct i2c_driver w83l785ts_driver = {
 
 struct w83l785ts_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -140,7 +141,7 @@ static int w83l785ts_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, w83l785ts_detect);
+       return i2c_probe(adapter, &addr_data, w83l785ts_detect);
 }
 
 /*
@@ -239,11 +240,19 @@ static int w83l785ts_detect(struct i2c_adapter *adapter, int address, int kind)
         */
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto exit_detach;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_temp1_input);
        device_create_file(&new_client->dev, &dev_attr_temp1_max);
 
        return 0;
 
+exit_detach:
+       i2c_detach_client(new_client);
 exit_free:
        kfree(data);
 exit:
@@ -252,15 +261,15 @@ exit:
 
 static int w83l785ts_detach_client(struct i2c_client *client)
 {
+       struct w83l785ts_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev, "Client deregistration failed, "
-                       "client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
        return 0;
 }
 
index cd170395a8c7ced66695536007f0684e2cf4201d..71c5a854ac5d646d31e03ad511ea5ceb00ef8af8 100644 (file)
@@ -4,12 +4,8 @@
 
 obj-$(CONFIG_I2C)              += i2c-core.o
 obj-$(CONFIG_I2C_CHARDEV)      += i2c-dev.o
-obj-$(CONFIG_I2C_SENSOR)       += i2c-sensor.o
 obj-y                          += busses/ chips/ algos/
 
-i2c-sensor-objs := i2c-sensor-detect.o i2c-sensor-vid.o
-
-
 ifeq ($(CONFIG_I2C_DEBUG_CORE),y)
 EXTRA_CFLAGS += -DDEBUG
 endif
index fb5b732238ed814095319f5e7518159cd6bbd8ac..df05df1a0ef61f20de8239e36bb3202ac7ae6ae5 100644 (file)
@@ -519,8 +519,6 @@ static u32 bit_func(struct i2c_adapter *adap)
 /* -----exported algorithm data: ------------------------------------- */
 
 static struct i2c_algorithm i2c_bit_algo = {
-       .name           = "Bit-shift algorithm",
-       .id             = I2C_ALGO_BIT,
        .master_xfer    = bit_xfer,
        .functionality  = bit_func,
 };
@@ -541,8 +539,6 @@ int i2c_bit_add_bus(struct i2c_adapter *adap)
        DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
 
        /* register new adapter to i2c module... */
-
-       adap->id |= i2c_bit_algo.id;
        adap->algo = &i2c_bit_algo;
 
        adap->timeout = 100;    /* default values, should       */
index e6cae39f47aa062c7f09eb67ed1500bf41dbf665..2db7bfc852252dbf1b74c29ede26071b522a92e1 100644 (file)
@@ -713,8 +713,6 @@ static u32 iic_func(struct i2c_adapter *adap)
 /* -----exported algorithm data: ------------------------------------- */
 
 static struct i2c_algorithm iic_algo = {
-       .name           = "ITE IIC algorithm",
-       .id             = I2C_ALGO_IIC,
        .master_xfer    = iic_xfer,
        .algo_control   = algo_control, /* ioctl */
        .functionality  = iic_func,
@@ -738,8 +736,6 @@ int i2c_iic_add_bus(struct i2c_adapter *adap)
                    adap->name));
 
        /* register new adapter to i2c module... */
-
-       adap->id |= iic_algo.id;
        adap->algo = &iic_algo;
 
        adap->timeout = 100;    /* default values, should       */
index cc3a952401f2ea8354cf89ac5e43c151bd151cbe..beb10edfe9c1774c7426945962b749b9831c7c88 100644 (file)
@@ -187,12 +187,14 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
        int numbytes = 0;
        int state;
        int ret;
+       int timeout = 100;
 
-       state = pca_status(adap);
-       if ( state != 0xF8 ) {
-               dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state );
-               /* FIXME: what to do. Force stop ? */
-               return -EREMOTEIO;
+       while ((state = pca_status(adap)) != 0xf8 && timeout--) {
+               msleep(10);
+       }
+       if (state != 0xf8) {
+               dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
+               return -EIO;
        }
 
        DEB1("{{{ XFER %d messages\n", num);
@@ -354,8 +356,6 @@ static int pca_init(struct i2c_algo_pca_data *adap)
 }
 
 static struct i2c_algorithm pca_algo = {
-       .name           = "PCA9564 algorithm",
-       .id             = I2C_ALGO_PCA,
        .master_xfer    = pca_xfer,
        .functionality  = pca_func,
 };
@@ -369,8 +369,6 @@ int i2c_pca_add_bus(struct i2c_adapter *adap)
        int rval;
 
        /* register new adapter to i2c module... */
-
-       adap->id |= pca_algo.id;
        adap->algo = &pca_algo;
 
        adap->timeout = 100;            /* default values, should       */
index 8d087dac32afc7e22575ff32be4c8a2262d3ddb1..6e498df1f717aea6f238b6ce91d990b9a7cbedfa 100644 (file)
@@ -459,8 +459,6 @@ static u32 pcf_func(struct i2c_adapter *adap)
 /* -----exported algorithm data: ------------------------------------- */
 
 static struct i2c_algorithm pcf_algo = {
-       .name           = "PCF8584 algorithm",
-       .id             = I2C_ALGO_PCF,
        .master_xfer    = pcf_xfer,
        .functionality  = pcf_func,
 };
@@ -476,8 +474,6 @@ int i2c_pcf_add_bus(struct i2c_adapter *adap)
        DEB2(dev_dbg(&adap->dev, "hw routines registered.\n"));
 
        /* register new adapter to i2c module... */
-
-       adap->id |= pcf_algo.id;
        adap->algo = &pcf_algo;
 
        adap->timeout = 100;            /* default values, should       */
index 422721b241e5a0914f5383502035eb3dffc1f165..2f8df81317ffe710be943ed99c52f57833b8ad9c 100644 (file)
@@ -158,8 +158,6 @@ static u32 sgi_func(struct i2c_adapter *adap)
 }
 
 static struct i2c_algorithm sgi_algo = {
-       .name           = "SGI algorithm",
-       .id             = I2C_ALGO_SGI,
        .master_xfer    = sgi_xfer,
        .functionality  = sgi_func,
 };
@@ -169,7 +167,6 @@ static struct i2c_algorithm sgi_algo = {
  */
 int i2c_sgi_add_bus(struct i2c_adapter *adap)
 {
-       adap->id |= sgi_algo.id;
        adap->algo = &sgi_algo;
 
        return i2c_add_adapter(adap);
index f2785499237bf10135f571c0ebfddb9b9e4e5474..8ed5ad12552fed1ccf1f6ee7669c54afd652cf83 100644 (file)
@@ -135,8 +135,6 @@ static u32 bit_func(struct i2c_adapter *adap)
 /* -----exported algorithm data: ------------------------------------- */
 
 static struct i2c_algorithm i2c_sibyte_algo = {
-       .name           = "SiByte algorithm",
-       .id             = I2C_ALGO_SIBYTE,
        .smbus_xfer     = smbus_xfer,
        .algo_control   = algo_control, /* ioctl */
        .functionality  = bit_func,
@@ -151,8 +149,6 @@ int i2c_sibyte_add_bus(struct i2c_adapter *i2c_