rocky hu | 24 May 18:36
Picon
Favicon

rocky hu与您共享了照片

If you are anxious for not find good supplier ? please contact us, we will  
offer you best service.
we are serious business person.

wholesale Louis Vuitton, Gucci, Fendi, Prada, Hermes, Chloe, Balenciage,  
Chanel, Coach, Jimmy choo, Juicy etc.

Such as Handbags, Wallets, T-shirt, sport shoes, Jerseys,Jackets,  
Jeans,Jewelry, hoody, Sunglasses, Belts, Bikini, Boots, the north face  
jacket ect

Website: www.sobagssoyou.com

Payment: Paypal, western union,Money Gram

Shipping: 5-6 business days
  more order, more discount

Hope to do business with you.
Email:cnwholesalelist <at> hotmail.com
_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Dan Carpenter | 24 May 17:58
Picon
Favicon

[patch] watchdog: sch56xx-common: set correct bits in register()

WDOG_NO_WAY_OUT (3) and WDOG_ACTIVE (0) are the bit numbers, not a mask.
So "data->wddev.status |= WDOG_ACTIVE;" was intended to set bit zero but
it is a no-op.

Signed-off-by: Dan Carpenter <dan.carpenter <at> oracle.com>

diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c
index 839087c..4380f5d 100644
--- a/drivers/hwmon/sch56xx-common.c
+++ b/drivers/hwmon/sch56xx-common.c
@@ -464,9 +464,9 @@ struct sch56xx_watchdog_data *sch56xx_watchdog_register(struct device *parent,
 	data->wddev.min_timeout = 1;
 	data->wddev.max_timeout = 255 * 60;
 	if (nowayout)
-		data->wddev.status |= WDOG_NO_WAY_OUT;
+		set_bit(WDOG_NO_WAY_OUT, &data->wddev.status);
 	if (output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)
-		data->wddev.status |= WDOG_ACTIVE;
+		set_bit(WDOG_ACTIVE, &data->wddev.status);

 	/* Since the watchdog uses a downcounter there is no register to read
 	   the BIOS set timeout from (if any was set at all) ->

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

clement clem | 23 May 18:25
Picon

Nuvoton NCT6776D - AsRock

Hello to all,

Have a new card AsRock B75 Pro 3 M yesterday.

This card uses a new chip Nuvoton NCT6776D.

Can we have full support for Lm-Sensors ?

For now only the temperature of my i3 2100 are displayed.


Thank you for your help.

Clem from South France

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Lucia Casati | 23 May 12:05

lavoriamo insieme

Salve,

vorrei cogliere questa occasione per presentarmi.
Il mio nome è Lucia Casati e sono la responsabile di Italy-SEO.

Lavoro al fianco di numerosi siti internet. Gestisco il loro SEO
in base alle particolarità dei maggiori motori di ricerca on line,
tra cui Google, Bing e Yahoo.

Lavorando al sito web di uno dei miei partner lavorativi,
ho incrociato lists.lm-sensors.org
Sono convinta di poter esserle utile per incrementare il traffico,
la visibilità e il Page Rank del suo sito.

Se interessato, sarei più che felice di elaborare meglio
i dettagli della mia proposta di assistenza.

Le auguro una buona giornata,

Lucia Casati
Italyseo.com

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Dmitriy Pinchukov | 23 May 11:37

ASUS Sabertooth Z77 / nct6775.ko report

Hi,

Got a new ASUS Sabertooth Z77 mobo recently and found out that lm-sensors didn't support
anything but the core temperatures and also a couple ones from the
'acpitz-virtual-0' device. Trying the trunk version of sensors-detect didn't help.

I then searched and finally found the shiny new 'nct6775' driver. Compiled and loaded it successfully
(linux 3.4.0 x86_64):

[ 1082.377370] nct6775: Found NCT6779D chip at 0x290

Here's how my sensors output looking now (lm-sensors 3.3.2 from Debian wheezy/sid):

acpitz-virtual-0
Adapter: Virtual device
temp1:        +27.8°C  (crit = +106.0°C)
temp2:        +29.8°C  (crit = +106.0°C)

coretemp-isa-0000
Adapter: ISA adapter
Physical id 0:  +45.0°C  (high = +85.0°C, crit = +105.0°C)
Core 0:         +44.0°C  (high = +85.0°C, crit = +105.0°C)
Core 1:         +45.0°C  (high = +85.0°C, crit = +105.0°C)
Core 2:         +43.0°C  (high = +85.0°C, crit = +105.0°C)
Core 3:         +43.0°C  (high = +85.0°C, crit = +105.0°C)

nct6779-isa-0290
Adapter: ISA adapter
in0:                    +1.00 V  (min =  +0.00 V, max =  +1.74 V)
in1:                    +1.03 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in2:                    +3.42 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in3:                    +3.42 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in4:                    +1.02 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in5:                    +2.04 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in6:                    +1.49 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in7:                    +3.41 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in8:                    +3.36 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in9:                    +1.06 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in10:                   +1.49 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in11:                   +1.49 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in12:                   +0.25 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in13:                   +0.18 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
in14:                   +1.49 V  (min =  +0.00 V, max =  +0.00 V)  ALARM
fan1:                     0 RPM  (min =    0 RPM)
fan2:                  1142 RPM  (min =    0 RPM)
fan3:                  1011 RPM  (min =    0 RPM)
fan4:                   922 RPM  (min =    0 RPM)
fan5:                     0 RPM  (min =    0 RPM)
SYSTIN:                 +36.0°C  (high =  +0.0°C, hyst =  +0.0°C)  ALARM  sensor = thermistor
CPUTIN:                  +0.5°C  (high = +80.0°C, hyst = +75.0°C)  sensor = thermistor
AUXTIN0:                 +0.0°C    sensor = thermistor
AUXTIN1:                 +0.0°C    sensor = thermistor
AUXTIN2:                 +0.0°C    sensor = thermistor
AUXTIN3:                 +0.0°C    sensor = thermistor
PCH_CHIP_CPU_MAX_TEMP:   +0.0°C
PCH_CHIP_TEMP:           +0.0°C
PCH_CPU_TEMP:            +0.0°C
PCH_MCH_TEMP:            +0.0°C
cpu0_vid:              +0.000 V
intrusion0:            ALARM
intrusion1:            ALARM

Here's my thoughts:

- only 5 fans are shown whereas the mobo has 8 fan connectors (two of which are 3-pin, the rest are 4-pin);
- this board has a lot of temperature sensors (the windows asus monitoring utility shows around 8 or 9 of them
I think), but only the SYSTIN seems to be reported correctly by this driver, the rest are zero;
- cpu0_vid has zero value as well;
- min/max values are zero for some of the sensors and the ALARM status is reported erroneously there;
- fan control *does* work via the /sys/devices/platform/nct6775.656/pwm* interface, both in PWM and DC
control modes; I can reduce their speed and fully stop them.

What do you guys think of this? My current sensors-detect output is in the attachment and is also available
at http://pastebin.com/BUs8e0sn. I also tried the 'lm75' and 'ds1621' drivers that it suggested, but
that didn't change the output of sensors and there weren't any messages in dmesg when I loaded them.

I will gladly present any additional info that might help to debug the issue or improve the
driver.

# sensors-detect revision 6040 (2012-04-09 22:33:35 +0300)
# Board: ASUSTeK COMPUTER INC. SABERTOOTH Z77

This program will help you determine which kernel modules you need
to load to use lm_sensors most effectively. It is generally safe
and recommended to accept the default answers to all questions,
unless you know what you're doing.

Some south bridges, CPUs or memory controllers contain embedded sensors.
Do you want to scan for them? This is totally safe. (YES/no): Silicon Integrated Systems SIS5595...                       No
VIA VT82C686 Integrated Sensors...                          No
VIA VT8231 Integrated Sensors...                            No
AMD K8 thermal sensors...                                   No
AMD Family 10h thermal sensors...                           No
AMD Family 11h thermal sensors...                           No
AMD Family 12h and 14h thermal sensors...                   No
AMD Family 15h thermal sensors...                           No
AMD Family 15h power sensors...                             No
Intel digital thermal sensor...                             Success!
    (driver `coretemp')
Intel AMB FB-DIMM thermal sensor...                         No
VIA C7 thermal sensor...                                    No
VIA Nano thermal sensor...                                  No

Some Super I/O chips contain embedded sensors. We have to write to
standard I/O ports to probe them. This is usually safe.
Do you want to scan for Super I/O sensors? (YES/no): Probing for Super-I/O at 0x2e/0x2f
Trying family `National Semiconductor/ITE'...               No
Trying family `SMSC'...                                     No
Trying family `VIA/Winbond/Nuvoton/Fintek'...               Yes
Found unknown chip with ID 0xc562
    (logical device B has address 0x290, could be sensors)
Probing for Super-I/O at 0x4e/0x4f
Trying family `National Semiconductor/ITE'...               No
Trying family `SMSC'...                                     No
Trying family `VIA/Winbond/Nuvoton/Fintek'...               No
Trying family `ITE'...                                      No

Some systems (mainly servers) implement IPMI, a set of common interfaces
through which system health data may be retrieved, amongst other things.
We first try to get the information from SMBIOS. If we don't find it
there, we have to read from arbitrary I/O ports to probe for such
interfaces. This is normally safe. Do you want to scan for IPMI
interfaces? (YES/no): Probing for `IPMI BMC KCS' at 0xca0...                      No
Probing for `IPMI BMC SMIC' at 0xca8...                     No

Some hardware monitoring chips are accessible through the ISA I/O ports.
We have to write to arbitrary I/O ports to probe them. This is usually
safe though. Yes, you do have ISA I/O ports even if you do not have any
ISA slots! Do you want to scan the ISA I/O ports? (YES/no): Probing for `National Semiconductor LM78' at 0x290...       No
Probing for `National Semiconductor LM79' at 0x290...       No
Probing for `Winbond W83781D' at 0x290...                   No
Probing for `Winbond W83782D' at 0x290...                   No

Lastly, we can probe the I2C/SMBus adapters for connected hardware
monitoring devices. This is the most risky part, and while it works
reasonably well on most systems, it has been reported to cause trouble
on some systems.
Do you want to probe the I2C/SMBus adapters now? (YES/no): Using driver `i2c-i801' for device 0000:00:1f.3: Intel Panther Point (PCH)

Next adapter: i915 gmbus disabled (i2c-0)
Do you want to scan it? (YES/no/selectively): 
Next adapter: i915 gmbus ssc (i2c-1)
Do you want to scan it? (YES/no/selectively): 
Next adapter: i915 gmbus vga (i2c-2)
Do you want to scan it? (YES/no/selectively): 
Next adapter: i915 gmbus panel (i2c-3)
Do you want to scan it? (YES/no/selectively): 
Next adapter: i915 gmbus dpc (i2c-4)
Do you want to scan it? (YES/no/selectively): 
Next adapter: i915 gmbus dpb (i2c-5)
Do you want to scan it? (YES/no/selectively): 
Next adapter: i915 gmbus reserved (i2c-6)
Do you want to scan it? (YES/no/selectively): Client found at address 0x18
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `National Semiconductor LM95245'...             No
Probing for `National Semiconductor LM64'...                No
Probing for `SMSC EMC1047'...                               No
Probing for `SMSC EMC1402'...                               No
Probing for `SMSC EMC1403'...                               No
Probing for `SMSC EMC1404'...                               No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x19
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `National Semiconductor LM95231'...             No
Probing for `National Semiconductor LM95241'...             No
Probing for `National Semiconductor LM95245'...             No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x1a
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x1b
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x1c
Probing for `Texas Instruments TMP421'...                   No
Probing for `SMSC EMC1072'...                               No
Probing for `SMSC EMC1073'...                               No
Probing for `SMSC EMC1074'...                               No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x1d
Probing for `Texas Instruments TMP421'...                   No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x1e
Probing for `Texas Instruments TMP421'...                   No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x1f
Probing for `Texas Instruments TMP421'...                   No
Probing for `ST STTS424'...                                 No
Probing for `ST STTS424E'...                                No
Probing for `ST STTS2002'...                                No
Probing for `ST STTS3000'...                                No
Probing for `NXP SE97/SE97B'...                             No
Probing for `NXP SE98'...                                   No
Probing for `Analog Devices ADT7408'...                     No
Probing for `IDT TS3000/TSE2002'...                         No
Probing for `Maxim MAX6604'...                              No
Probing for `Microchip MCP9804'...                          No
Probing for `Microchip MCP98242'...                         No
Probing for `Microchip MCP98243'...                         No
Probing for `Microchip MCP9843'...                          No
Probing for `ON CAT6095/CAT34TS02'...                       No
Probing for `Atmel AT30TS00'...                             No
Client found at address 0x28
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Analog Devices ADM1029'...                     No
Probing for `ITE IT8712F'...                                No
Client found at address 0x29
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `National Semiconductor LM95245'...             No
Probing for `Analog Devices ADM1029'...                     No
Probing for `ITE IT8712F'...                                No
Probing for `SMSC EMC1402'...                               No
Probing for `SMSC EMC1403'...                               No
Probing for `SMSC EMC1404'...                               No
Client found at address 0x2a
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Texas Instruments TMP421'...                   No
Probing for `National Semiconductor LM95231'...             No
Probing for `National Semiconductor LM95241'...             No
Probing for `Analog Devices ADM1029'...                     No
Probing for `ITE IT8712F'...                                No
Client found at address 0x2b
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `National Semiconductor LM95231'...             No
Probing for `National Semiconductor LM95241'...             No
Probing for `Analog Devices ADM1029'...                     No
Probing for `ITE IT8712F'...                                No
Client found at address 0x2c
Probing for `Myson MTP008'...                               No
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `National Semiconductor LM85'...                No
Probing for `National Semiconductor LM96000 or PC8374L'...  No
Probing for `Analog Devices ADM1027'...                     No
Probing for `Analog Devices ADT7460 or ADT7463'...          No
Probing for `SMSC EMC6D100 or EMC6D101'...                  No
Probing for `SMSC EMC6D102'...                              No
Probing for `SMSC EMC6D103'...                              No
Probing for `SMSC EMC6D103S or EMC2300'...                  No
Probing for `SMSC EMC6W201'...                              No
Probing for `Winbond WPCD377I'...                           No
Probing for `Analog Devices ADT7470'...                     No
Probing for `Analog Devices ADT7473'...                     No
Probing for `Analog Devices ADT7476'...                     No
Probing for `Analog Devices ADT7490'...                     No
Probing for `Andigilog aSC7611'...                          No
Probing for `Andigilog aSC7621'...                          No
Probing for `National Semiconductor LM87'...                No
Probing for `Analog Devices ADM1024'...                     No
Probing for `National Semiconductor LM93'...                No
Probing for `National Semiconductor LM94 or LM96194'...     No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83791D'...                            No
Probing for `Winbond W83792D'...                            No
Probing for `Winbond W83793R/G'...                          No
Probing for `Nuvoton W83795G/ADG'...                        No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Genesys Logic GL518SM'...                      No
Probing for `Genesys Logic GL520SM'...                      No
Probing for `Analog Devices ADM9240'...                     No
Probing for `Dallas Semiconductor DS1780'...                No
Probing for `National Semiconductor LM81'...                No
Probing for `Analog Devices ADM1026'...                     No
Probing for `Analog Devices ADM1025'...                     No
Probing for `Philips NE1619'...                             No
Probing for `Maxim MAX6639'...                              No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `Analog Devices ADM1029'...                     No
Probing for `Analog Devices ADM1030'...                     No
Probing for `Analog Devices ADM1031'...                     No
Probing for `Analog Devices ADM1022'...                     No
Probing for `Texas Instruments THMC50'...                   No
Probing for `ITE IT8712F'...                                No
Probing for `ALi M5879'...                                  No
Probing for `SMSC LPC47M15x/192/292/997'...                 No
Probing for `SMSC DME1737'...                               No
Probing for `SMSC SCH5027D-NW'...                           No
Probing for `Winbond W83791SD'...                           No
Client found at address 0x2d
Probing for `Myson MTP008'...                               No
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `National Semiconductor LM85'...                No
Probing for `National Semiconductor LM96000 or PC8374L'...  No
Probing for `Analog Devices ADM1027'...                     No
Probing for `Analog Devices ADT7460 or ADT7463'...          No
Probing for `SMSC EMC6D100 or EMC6D101'...                  No
Probing for `SMSC EMC6D102'...                              No
Probing for `SMSC EMC6D103'...                              No
Probing for `SMSC EMC6D103S or EMC2300'...                  No
Probing for `SMSC EMC6W201'...                              No
Probing for `Winbond WPCD377I'...                           No
Probing for `Analog Devices ADT7473'...                     No
Probing for `Analog Devices ADT7476'...                     No
Probing for `Analog Devices ADT7490'...                     No
Probing for `Andigilog aSC7611'...                          No
Probing for `Andigilog aSC7621'...                          No
Probing for `National Semiconductor LM87'...                No
Probing for `Analog Devices ADM1024'...                     No
Probing for `National Semiconductor LM93'...                No
Probing for `National Semiconductor LM94 or LM96194'...     No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83783S'...                            No
Probing for `Winbond W83791D'...                            No
Probing for `Winbond W83792D'...                            No
Probing for `Winbond W83793R/G'...                          No
Probing for `Nuvoton W83795G/ADG'...                        No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Winbond W83L784R/AR/G'...                      No
Probing for `Winbond W83L785R/G'...                         No
Probing for `Genesys Logic GL518SM'...                      No
Probing for `Genesys Logic GL520SM'...                      No
Probing for `Genesys Logic GL525SM'...                      No
Probing for `Analog Devices ADM9240'...                     No
Probing for `Dallas Semiconductor DS1780'...                No
Probing for `National Semiconductor LM81'...                No
Probing for `Analog Devices ADM1026'...                     No
Probing for `Analog Devices ADM1025'...                     No
Probing for `Philips NE1619'...                             No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `Analog Devices ADM1029'...                     No
Probing for `Analog Devices ADM1030'...                     No
Probing for `Analog Devices ADM1031'...                     No
Probing for `Analog Devices ADM1022'...                     No
Probing for `Texas Instruments THMC50'...                   No
Probing for `VIA VT1211 (I2C)'...                           No
Probing for `ITE IT8712F'...                                No
Probing for `ALi M5879'...                                  No
Probing for `SMSC LPC47M15x/192/292/997'...                 No
Probing for `SMSC DME1737'...                               No
Probing for `SMSC SCH5027D-NW'...                           No
Probing for `Fintek F75373S/SG'...                          No
Probing for `Fintek F75375S/SP'...                          No
Probing for `Fintek F75387SG/RG'...                         No
Probing for `Winbond W83791SD'...                           No
Client found at address 0x2e
Probing for `Myson MTP008'...                               No
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `National Semiconductor LM85'...                No
Probing for `National Semiconductor LM96000 or PC8374L'...  No
Probing for `Analog Devices ADM1027'...                     No
Probing for `Analog Devices ADT7460 or ADT7463'...          No
Probing for `SMSC EMC6D100 or EMC6D101'...                  No
Probing for `SMSC EMC6D102'...                              No
Probing for `SMSC EMC6D103'...                              No
Probing for `SMSC EMC6D103S or EMC2300'...                  No
Probing for `SMSC EMC6W201'...                              No
Probing for `Winbond WPCD377I'...                           No
Probing for `Analog Devices ADT7467 or ADT7468'...          No
Probing for `Analog Devices ADT7470'...                     No
Probing for `Analog Devices ADT7473'...                     No
Probing for `Analog Devices ADT7475'...                     No
Probing for `Analog Devices ADT7476'...                     No
Probing for `Analog Devices ADT7490'...                     No
Probing for `Andigilog aSC7611'...                          No
Probing for `Andigilog aSC7621'...                          No
Probing for `National Semiconductor LM87'...                No
Probing for `Analog Devices ADM1024'...                     No
Probing for `National Semiconductor LM93'...                No
Probing for `National Semiconductor LM94 or LM96194'...     No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83791D'...                            No
Probing for `Winbond W83792D'...                            No
Probing for `Winbond W83793R/G'...                          No
Probing for `Nuvoton W83795G/ADG'...                        No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Winbond W83L786NR/NG/R/G'...                   No
Probing for `Winbond W83L785TS-S'...                        No
Probing for `Analog Devices ADM9240'...                     No
Probing for `Dallas Semiconductor DS1780'...                No
Probing for `National Semiconductor LM81'...                No
Probing for `Analog Devices ADM1026'...                     No
Probing for `Analog Devices ADM1025'...                     No
Probing for `Maxim MAX6639'...                              No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `Analog Devices ADM1029'...                     No
Probing for `Analog Devices ADM1030'...                     No
Probing for `Analog Devices ADM1031'...                     No
Probing for `Analog Devices ADM1022'...                     No
Probing for `Texas Instruments THMC50'...                   No
Probing for `Analog Devices ADM1028'...                     No
Probing for `Texas Instruments THMC51'...                   No
Probing for `ITE IT8712F'...                                No
Probing for `SMSC DME1737'...                               No
Probing for `SMSC SCH5027D-NW'...                           No
Probing for `SMSC EMC2103'...                               No
Probing for `Fintek F75373S/SG'...                          No
Probing for `Fintek F75375S/SP'...                          No
Probing for `Fintek F75387SG/RG'...                         No
Probing for `Winbond W83791SD'...                           No
Client found at address 0x2f
Probing for `National Semiconductor LM78'...                No
Probing for `National Semiconductor LM79'...                No
Probing for `National Semiconductor LM80'...                No
Probing for `National Semiconductor LM96080'...             No
Probing for `Analog Devices ADT7470'...                     No
Probing for `Winbond W83781D'...                            No
Probing for `Winbond W83782D'...                            No
Probing for `Winbond W83791D'...                            No
Probing for `Winbond W83792D'...                            No
Probing for `Winbond W83793R/G'...                          No
Probing for `Nuvoton W83795G/ADG'...                        No
Probing for `Winbond W83627HF'...                           No
Probing for `Winbond W83627EHF'...                          No
Probing for `Winbond W83627DHG/W83667HG/W83677HG'...        No
Probing for `Asus AS99127F (rev.1)'...                      No
Probing for `Asus AS99127F (rev.2)'...                      No
Probing for `Asus ASB100 Bach'...                           No
Probing for `Winbond W83L786NR/NG/R/G'...                   No
Probing for `Analog Devices ADM9240'...                     No
Probing for `Dallas Semiconductor DS1780'...                No
Probing for `National Semiconductor LM81'...                No
Probing for `Maxim MAX6639'...                              No
Probing for `Analog Devices ADM1029'...                     No
Probing for `ITE IT8712F'...                                No
Probing for `Fintek custom power control IC'...             No
Probing for `Winbond W83791SD'...                           No
Client found at address 0x48
Probing for `National Semiconductor LM75'...                Success!
    (confidence 3, driver `lm75')
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  Success!
    (confidence 3, driver `lm75')
Probing for `National Semiconductor LM77'...                No
Probing for `Analog Devices ADT7410'...                     No
Probing for `Analog Devices ADT7411'...                     No
Probing for `Dallas Semiconductor DS1621/DS1631'...         Success!
    (confidence 2, driver `ds1621')
Probing for `Maxim MAX6642'...                              No
Probing for `National Semiconductor LM73'...                No
Probing for `National Semiconductor LM92'...                No
Probing for `National Semiconductor LM76'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `NXP/Philips SA56004'...                        No
Probing for `SMSC EMC1023'...                               No
Probing for `SMSC EMC1043'...                               No
Probing for `SMSC EMC1053'...                               No
Probing for `SMSC EMC1063'...                               No
Client found at address 0x49
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `National Semiconductor LM77'...                No
Probing for `Analog Devices ADT7410'...                     No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Maxim MAX6642'...                              No
Probing for `National Semiconductor LM73'...                No
Probing for `National Semiconductor LM92'...                No
Probing for `National Semiconductor LM76'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `NXP/Philips SA56004'...                        No
Probing for `SMSC EMC1023'...                               No
Probing for `SMSC EMC1043'...                               No
Probing for `SMSC EMC1053'...                               No
Probing for `SMSC EMC1063'...                               No
Client found at address 0x4a
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `National Semiconductor LM77'...                No
Probing for `Analog Devices ADT7410'...                     No
Probing for `Analog Devices ADT7411'...                     No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Maxim MAX6642'...                              No
Probing for `National Semiconductor LM73'...                No
Probing for `National Semiconductor LM92'...                No
Probing for `National Semiconductor LM76'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `NXP/Philips SA56004'...                        No
Client found at address 0x4b
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `National Semiconductor LM77'...                No
Probing for `Analog Devices ADT7410'...                     No
Probing for `Analog Devices ADT7411'...                     No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Maxim MAX6642'...                              No
Probing for `National Semiconductor LM92'...                No
Probing for `National Semiconductor LM76'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `NXP/Philips SA56004'...                        No
Probing for `Analog Devices ADT7481'...                     No
Client found at address 0x4c
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `Analog Devices ADT7466'...                     No
Probing for `Andigilog aSC7511'...                          No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Global Mixed-mode Technology G781'...          No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6642'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `National Semiconductor LM90'...                No
Probing for `National Semiconductor LM89/LM99'...           No
Probing for `National Semiconductor LM86'...                No
Probing for `Analog Devices ADM1032'...                     No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6657/MAX6658/MAX6659'...              No
Probing for `Maxim MAX6648/MAX6649/MAX6692'...              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Winbond W83L771W/G'...                         No
Probing for `Winbond W83L771AWG/ASG'...                     No
Probing for `Texas Instruments TMP401'...                   No
Probing for `Texas Instruments TMP411'...                   No
Probing for `Texas Instruments TMP421'...                   No
Probing for `Texas Instruments TMP422'...                   No
Probing for `Texas Instruments TMP423'...                   No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `National Semiconductor LM95245'...             No
Probing for `National Semiconductor LM63'...                No
Probing for `National Semiconductor LM96163'...             No
Probing for `Fintek F75363SG'...                            No
Probing for `National Semiconductor LM73'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `Analog Devices ADT7461'...                     No
Probing for `Analog Devices ADT7461A, ON Semiconductor NCT1008'... No
Probing for `NXP/Philips SA56004'...                        No
Probing for `Analog Devices ADT7481'...                     No
Probing for `Fintek F75383S/M'...                           No
Probing for `SMSC EMC1002'...                               No
Probing for `SMSC EMC1023'...                               No
Probing for `SMSC EMC1033'...                               No
Probing for `SMSC EMC1043'...                               No
Probing for `SMSC EMC1046'...                               No
Probing for `SMSC EMC1053'...                               No
Probing for `SMSC EMC1063'...                               No
Probing for `SMSC EMC1072'...                               No
Probing for `SMSC EMC1073'...                               No
Probing for `SMSC EMC1074'...                               No
Probing for `SMSC EMC1402'...                               No
Probing for `SMSC EMC1403'...                               No
Probing for `SMSC EMC1404'...                               No
Probing for `SMSC EMC1423'...                               No
Probing for `SMSC EMC1424'...                               No
Client found at address 0x4d
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Global Mixed-mode Technology G781'...          No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6642'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `National Semiconductor LM89/LM99'...           No
Probing for `Analog Devices ADM1032'...                     No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6659'...                              No
Probing for `Maxim MAX6646'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Texas Instruments TMP411'...                   No
Probing for `Texas Instruments TMP421'...                   No
Probing for `Texas Instruments TMP422'...                   No
Probing for `Texas Instruments TMP423'...                   No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `National Semiconductor LM95245'...             No
Probing for `National Semiconductor LM73'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `Analog Devices ADT7461'...                     No
Probing for `Analog Devices ADT7461A, ON Semiconductor NCT1008'... No
Probing for `NXP/Philips SA56004'...                        No
Probing for `Fintek F75384S/M'...                           No
Probing for `SMSC EMC1002'...                               No
Probing for `SMSC EMC1023'...                               No
Probing for `SMSC EMC1033'...                               No
Probing for `SMSC EMC1043'...                               No
Probing for `SMSC EMC1046'...                               No
Probing for `SMSC EMC1053'...                               No
Probing for `SMSC EMC1063'...                               No
Probing for `SMSC EMC1402'...                               No
Probing for `SMSC EMC1403'...                               No
Probing for `SMSC EMC1404'...                               No
Client found at address 0x4e
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Analog Devices ADM1021'...                     No
Probing for `Analog Devices ADM1021A/ADM1023'...            No
Probing for `Maxim MAX1617'...                              No
Probing for `Maxim MAX1617A'...                             No
Probing for `Maxim MAX1668'...                              No
Probing for `Maxim MAX1805'...                              No
Probing for `Maxim MAX1989'...                              No
Probing for `Maxim MAX6642'...                              No
Probing for `Maxim MAX6655/MAX6656'...                      No
Probing for `TI THMC10'...                                  No
Probing for `National Semiconductor LM84'...                No
Probing for `Genesys Logic GL523SM'...                      No
Probing for `Onsemi MC1066'...                              No
Probing for `Maxim MAX1618'...                              No
Probing for `Maxim MAX1619'...                              No
Probing for `National Semiconductor LM82/LM83'...           No
Probing for `Maxim MAX6654'...                              No
Probing for `Maxim MAX6690'...                              No
Probing for `Maxim MAX6659'...                              No
Probing for `Maxim MAX6647'...                              No
Probing for `Maxim MAX6680/MAX6681'...                      No
Probing for `Maxim MAX6695/MAX6696'...                      No
Probing for `Texas Instruments TMP411'...                   No
Probing for `Texas Instruments TMP421'...                   No
Probing for `Texas Instruments TMP422'...                   No
Probing for `Texas Instruments AMC6821'...                  No
Probing for `National Semiconductor LM64'...                No
Probing for `National Semiconductor LM73'...                No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `NXP/Philips SA56004'...                        No
Probing for `Fintek F75121R/F75122R/RG (VID+GPIO)'...       No
Probing for `Fintek F75111R/RG/N (GPIO)'...                 No
Probing for `ITE IT8201R/IT8203R/IT8206R/IT8266R'...        No
Client found at address 0x4f
Probing for `National Semiconductor LM75'...                No
Probing for `National Semiconductor LM75A'...               No
Probing for `Dallas Semiconductor DS75'...                  No
Probing for `Dallas Semiconductor DS1621/DS1631'...         No
Probing for `Maxim MAX6642'...                              No
Probing for `Texas Instruments TMP421'...                   No
Probing for `Texas Instruments TMP422'...                   No
Probing for `Maxim MAX6633/MAX6634/MAX6635'...              No
Probing for `NXP/Philips SA56004'...                        No
Client found at address 0x58
Probing for `Analog Devices ADT7462'...                     No
Probing for `Andigilog aSC7512'...                          No
Client found at address 0x5c
Probing for `Analog Devices ADT7462'...                     No
Probing for `SMSC EMC1072'...                               No
Probing for `SMSC EMC1073'...                               No
Probing for `SMSC EMC1074'...                               No
Client found at address 0x73
Probing for `FSC Poseidon I'...                             No
Probing for `FSC Poseidon II'...                            No
Probing for `FSC Scylla'...                                 No
Probing for `FSC Hermes'...                                 No
Probing for `FSC Heimdal'...                                No
Probing for `FSC Heracles'...                               No
Probing for `FSC Hades'...                                  No
Probing for `FSC Syleus'...                                 No
Client found at address 0x77
Probing for `Asus Mozart-2'...                              No

Next adapter: i915 gmbus dpd (i2c-7)
Do you want to scan it? (YES/no/selectively): 
Next adapter: DPDDC-C (i2c-8)
Do you want to scan it? (YES/no/selectively): 
Next adapter: DPDDC-D (i2c-9)
Do you want to scan it? (YES/no/selectively): 
Now follows a summary of the probes I have just done.
Just press ENTER to continue: 
Driver `lm75':
  * Bus `i915 gmbus reserved'
    Busdriver `drm', I2C address 0x48
    Chip `National Semiconductor LM75' (confidence: 3)

Driver `coretemp':
  * Chip `Intel digital thermal sensor' (confidence: 9)

Do you want to overwrite /etc/sysconfig/lm_sensors? (YES/no): Copy prog/init/lm_sensors.init to /etc/init.d/lm_sensors
for initialization at boot time.
You should now start the lm_sensors service to load the required
kernel modules.

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
James | 21 May 15:45
Picon

ASRock 970 Extreme3

I use the nct6776-isa-0290
Adapter: ISA adapter

I have 3 fans:
1. The CPU fan (about 3300 RPM)
2. The rear case fan (about 1050 RPM)
3. The front case fan (about 1350 RPM)

Do the fans in Power Supplies typically get monitored?

I have 6 fan connectors:
1. Chassis fan connector (#12 on the motherboard)
2. Chassis fan connector (#15 on the motherboard)
3. Chassis fan connector (#2 on the motherboard)
1. CPU fan connector (#6 on the motherboard)
2. CPU fan connector (#5 on the motherboard)
1. Power fan connector (#10 on the motherboard)

Maybe someone can see a pattern.

1. I plugged the rear case fan in #12
fan1 was 1060 RPM (the rear case fan probably)
fan2 was 3300 RPM (the CPU  fan probably)
other fans reported 0 RPMs

2. I plugged the rear case fan in #2
all fans reported 0 RPM
other fans reported 0 RPMs

3. I plugged the rear case fan in #12 and the front case fan in #15.
fan1 was 1053 RPM (the rear case fan probably)
fan2 was 3316 (the CPU fan probably)
other fans reported 0 RPMs

4. I plugged the rear case fan in #10 and the front case fan in #12.
fan1 was 1384 (the front case fan probably)
other fans reported 0 RPMs

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

Guenter Roeck | 21 May 04:40

[PATCH] hwmon: Driver for Nuvoton NCT6775F, NCT6776F, and NCT6779D

This driver will replace the w83627ehf driver for NCT6775F and NCT6776F,
and provides support for NCT6779D.

Signed-off-by: Guenter Roeck <linux <at> roeck-us.net>
---

Successfully tested on all supported chips. Time to submit for a first round of
reviews.

A new driver was chosen instead of adding support for NCT6779D to the w83627ehf
driver, since the amount of conditional code was getting too large to manage.
Also, with a new driver it was easier to implement additional fan control
support.

The driver implements a number of non-standard sysfs attributes for fan control.

TODO: Update Documentation/hwmon/nct6775 to list all supported sysfs attributes
(after we have an agreement about the non-standard attributes).

 Documentation/hwmon/nct6775 |  138 ++
 drivers/hwmon/Kconfig       |   13 +
 drivers/hwmon/Makefile      |    1 +
 drivers/hwmon/nct6775.c     | 3832 +++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 3984 insertions(+), 0 deletions(-)
 create mode 100644 Documentation/hwmon/nct6775
 create mode 100644 drivers/hwmon/nct6775.c

diff --git a/Documentation/hwmon/nct6775 b/Documentation/hwmon/nct6775
new file mode 100644
index 0000000..c1e4868
--- /dev/null
+++ b/Documentation/hwmon/nct6775
 <at>  <at>  -0,0 +1,138  <at>  <at> 
+Note
+====
+
+This driver supercedes the NCT6775F and NCT6776F support in the W83627EHF
+driver.
+
+Kernel driver NCT6775
+=======================
+
+Supported chips:
+  * Nuvoton NCT6775F/W83667HG-I
+    Prefix: 'nct6775'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6776F
+    Prefix: 'nct6776'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6779D
+    Prefix: 'nct6779'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+
+Authors:
+        Guenter Roeck <linux <at> roeck-us.net>
+
+Description
+-----------
+
+This driver implements support for the Nuvoton NCT6775F, NCT6776F, and NCT6779D
+super I/O chips. We will refer to them collectively as Nuvoton chips.
+
+The chips implement up to 8 temperature sensors depending on the chip type and
+configuration. Temperatures used to control fan speed are reported separately.
+There are 4 to 5 fan rotation speed sensors, 8 to 15 analog voltage sensors,
+one VID, alarms with beep warnings (control unimplemented), and some automatic
+fan regulation strategies (plus manual fan control mode).
+
+The temperature sensor sources on all chips are configurable. temp4 and higher
+attributes are only reported if its temperature source differs from the
+temperature sources of the already reported temperature sensors.
+The configured source for each of the temperature sensors is provided
+in tempX_label.
+
+Temperatures are measured in degrees Celsius and measurement resolution is
+either 1 degC or 0.5 degC, depending on the temperature source and
+configuration. An alarm is triggered when the temperature gets higher than
+the high limit; it stays on until the temperature falls below the hysteresis
+value. Alarms are only supported for temp1, temp2, and temp3.
+
+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. The driver sets the most
+suitable fan divisor itself. Some fans might not be present because they
+share pins with other functions.
+
+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.
+
+The driver supports automatic fan control mode known as Thermal Cruise.
+In this mode, the chip attempts to keep the measured temperature in a
+predefined temperature range. If the temperature goes out of range, fan
+is driven slower/faster to reach the predefined range again.
+
+The mode works for fan1-fan5.
+
+The temperature source used to control pwm1..pwm5 can be configured with
+pwm[1..5]_temp_sel and pwm[1..5]_weight_temp_sel. The value reported and
+configured with those attributes is the temperature sensor attribute index.
+For example, to map the source of temp1_input to pwm1_temp_sel, write 1
+into the pwm1_temp_sel attribute.
+
+sysfs attributes
+----------------
+
+name - this is a standard hwmon device entry, it contains the name of
+       the device (see the prefix in the list of supported devices at
+       the top of this file)
+
+pwm[1-5] - this file stores PWM duty cycle or DC value (fan speed) in range:
+	   0 (stop) to 255 (full)
+
+pwm[1-5]_enable - this file controls mode of fan/temperature control:
+	* 0 Fan control disabled (fans set to maximum speed)
+	* 1 Manual mode, write to pwm file any value 0-255 (full speed)
+	* 2 "Thermal Cruise" mode
+	* 3 "Fan Speed Cruise" mode
+	* 4 "Smart Fan III" mode (NCT6775F only)
+	* 5 "Smart Fan IV" mode
+
+pwm[1-5]_mode - controls if output is PWM or DC level
+        * 0 DC output (0 - 12v)
+        * 1 PWM output
+
+Thermal Cruise mode
+-------------------
+
+If the temperature is in the range defined by:
+
+pwm[1-5]_target 	Target temperature, unit millidegree Celsius
+			(range 0 - 127000)
+pwm[1-5]_auto_temp1_hyst
+			Hysteresis, unit millidegree Celsius
+			Hysteresis value is relative to pwm[1-5]_auto_temp1.
+
+there are no changes to fan speed. Once the temperature leaves the interval,
+fan speed increases (temp is higher) or decreases if lower than desired,
+using the following steps and times.
+
+pwm[1-5]_start_output	fan pwm start value (range 1 - 255), to start fan
+			when the temperature is above defined range.
+pwm[1-5]_stop_output	fan pwm (range 1 - 255) to stop fan.
+pwm[1-5]_step_up_time	milliseconds [ms] before fan speed is increased
+pwm[1-5]_step_down_time	milliseconds [ms] before fan speed is decreased
+pwm[1-5]_stop_time	how many milliseconds [ms] must elapse to switch
+                      	corresponding fan off. (when the temperature was below
+                      	defined range).
+
+Speed Cruise mode
+-----------------
+
+This modes tries to keep the fan speed constant.
+Untested; use at your own risk.
+
+
+Usage Notes
+-----------
+
+On various ASUS boards with NCT6776F, it appears that CPUTIN is not really
+connected to anything and floats, or that it is connected to some non-standard
+temperature measurement device. As a result, the temperature reported on CPUTIN
+will not reflect a usable value. It often reports unreasonablyy high
+temperatures, and in some cases the reported temperature declines if the actual
+temperature increases (similar to the raw PECI temperature value - see PECI
+specification for details). CPUTIN should therefore be be ignored on ASUS
+boards. The CPU temperature on ASUS boards is reported from PECI 0.
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 1c7bbd4..542b73e 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
 <at>  <at>  -824,6 +824,19  <at>  <at>  config SENSORS_MCP3021
 	  This driver can also be built as a module.  If so, the module
 	  will be called mcp3021.
 
+config SENSORS_NCT6775
+	tristate "Nuvoton NCT6775F, NCT6776F, NCT6779D"
+	depends on !PPC && EXPERIMENTAL
+	select HWMON_VID
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  functionality of the Nuvoton NCT6775F, NCT6776F, and NCT6779D
+	  Super-I/O chips. It replaces the w83627ehf driver for NCT6775F
+	  and NCT6776F.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called nct6775.
+
 config SENSORS_NTC_THERMISTOR
 	tristate "NTC thermistor support"
 	depends on EXPERIMENTAL
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index e1eeac1..37e728f 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
 <at>  <at>  -97,6 +97,7  <at>  <at>  obj-$(CONFIG_SENSORS_MAX6642)	+= max6642.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
 obj-$(CONFIG_SENSORS_MCP3021)	+= mcp3021.o
+obj-$(CONFIG_SENSORS_NCT6775)	+= nct6775.o
 obj-$(CONFIG_SENSORS_NTC_THERMISTOR)	+= ntc_thermistor.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c
new file mode 100644
index 0000000..f32346d
--- /dev/null
+++ b/drivers/hwmon/nct6775.c
 <at>  <at>  -0,0 +1,3832  <at>  <at> 
+/*
+ * nct6775 - Driver for the hardware monitoring functionality of
+ *	       Nuvoton NCT677x Super-I/O chips
+ *
+ * Copyright (C) 2012  Guenter Roeck <linux <at> roeck-us.net>
+ *
+ * Derived from w83627ehf driver
+ * Copyright (C) 2005-2011  Jean Delvare <khali <at> linux-fr.org>
+ * Copyright (C) 2006  Yuan Mu (Winbond),
+ *		       Rudolf Marek <r.marek <at> assembler.cz>
+ *		       David Hubbard <david.c.hubbard <at> gmail.com>
+ *		       Daniel J Blueman <daniel.blueman <at> gmail.com>
+ * Copyright (C) 2010  Sheng-Yuan Huang (Nuvoton) (PS00)
+ *
+ * Shamelessly ripped from the w83627hf driver
+ * Copyright (C) 2003  Mark Studebaker
+ *
+ * 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.
+ *
+ *
+ * Supports the following chips:
+ *
+ * Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
+ * nct6775f     9      4       3       6+3    0xb470 0xc1    0x5ca3
+ * nct6776f     9      5       3       6+3    0xc330 0xc1    0x5ca3
+ * nct6779d    15      5       5       2+5    0xc560 0xc1    0x5ca3
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/acpi.h>
+#include <linux/io.h>
+#include "lm75.h"
+
+#define TESTING
+
+enum kinds { nct6775, nct6776, nct6779 };
+
+/* used to set data->name = nct6775_device_names[data->sio_kind] */
+static const char * const nct6775_device_names[] = {
+	"nct6775",
+	"nct6776",
+	"nct6779",
+};
+
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
+static unsigned short fan_debounce;
+module_param(fan_debounce, ushort, 0);
+MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
+
+#define DRVNAME "nct6775"
+
+/*
+ * Super-I/O constants and functions
+ */
+
+#define NCT6775_LD_ACPI		0x0a
+#define NCT6775_LD_HWM		0x0b
+#define NCT6775_LD_VID		0x0d
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
+#define SIO_REG_EN_VRM10	0x2C	/* GPIO3, GPIO4 selection */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
+#define SIO_REG_VID_CTRL	0xF0	/* VID control */
+#define SIO_REG_VID_DATA	0xF1	/* VID data */
+
+#define SIO_NCT6775_ID		0xb470
+#define SIO_NCT6776_ID		0xc330
+#define SIO_NCT6779_ID		0xc560
+#define SIO_ID_MASK		0xFFF0
+
+static inline void
+superio_outb(int ioreg, int reg, int val)
+{
+	outb(reg, ioreg);
+	outb(val, ioreg + 1);
+}
+
+static inline int
+superio_inb(int ioreg, int reg)
+{
+	outb(reg, ioreg);
+	return inb(ioreg + 1);
+}
+
+static inline void
+superio_select(int ioreg, int ld)
+{
+	outb(SIO_REG_LDSEL, ioreg);
+	outb(ld, ioreg + 1);
+}
+
+static inline void
+superio_enter(int ioreg)
+{
+	outb(0x87, ioreg);
+	outb(0x87, ioreg);
+}
+
+static inline void
+superio_exit(int ioreg)
+{
+	outb(0xaa, ioreg);
+	outb(0x02, ioreg);
+	outb(0x02, ioreg + 1);
+}
+
+/*
+ * ISA constants
+ */
+
+#define IOREGION_ALIGNMENT	(~7)
+#define IOREGION_OFFSET		5
+#define IOREGION_LENGTH		2
+#define ADDR_REG_OFFSET		0
+#define DATA_REG_OFFSET		1
+
+#define NCT6775_REG_BANK	0x4E
+#define NCT6775_REG_CONFIG	0x40
+
+/*
+ * Not currently used:
+ * REG_MAN_ID has the value 0x5ca3 for all supported chips.
+ * REG_CHIP_ID == 0x88/0xa1/0xc1 depending on chip model.
+ * REG_MAN_ID is at port 0x4f
+ * REG_CHIP_ID is at port 0x58
+ */
+
+/* Voltage min/max registers for nr=7..14 are in bank 5 */
+
+static const u16 NCT6775_REG_IN_MAX[] = {
+	0x2b, 0x2d, 0x2f, 0x31, 0x33, 0x35, 0x37, 0x554, 0x556, 0x558, 0x55a,
+	0x55c, 0x55e, 0x560, 0x562 };
+static const u16 NCT6775_REG_IN_MIN[] = {
+	0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x555, 0x557, 0x559, 0x55b,
+	0x55d, 0x55f, 0x561, 0x563 };
+static const u16 NCT6775_REG_IN[] = {
+	0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x550, 0x551, 0x552
+};
+
+static const u16 NCT6779_REG_IN[] = {
+	0x480, 0x481, 0x482, 0x483, 0x484, 0x485, 0x486, 0x487,
+	0x488, 0x489, 0x48a, 0x48b, 0x48c, 0x48d, 0x48e
+};
+
+#define NCT6775_REG_VBAT		0x5D
+#define NCT6775_REG_DIODE		0x5E
+
+#define NCT6775_REG_FANDIV1		0x506
+#define NCT6775_REG_FANDIV2		0x507
+
+#define NCT6775_REG_CR_FAN_DEBOUNCE	0xf0
+
+static const u16 NCT6775_REG_ALARM[6] = { 0x459, 0x45A, 0x45B };
+static const u16 NCT6779_REG_ALARM[6] = { 0x459, 0x45A, 0x45B, 0x568 };
+
+/* 0..15 voltages, 16..23 fans, 24..31 temperatures */
+
+static const s8 NCT6775_ALARM_BITS[]
+	= { 0, 1, 2, 3, 8, 21, 20, 16,		/* in0.. in7 */
+	    17, -1, -1, -1, -1, -1, -1,		/* in8..in14 */
+	    -1,					/* unused */
+	    6, 7, 11, 10, 23,			/* fan1..fan5 */
+	    -1, -1, -1,				/* unused */
+	    4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	    12, -1 };				/* intrusion0, intrusion1 */
+
+static const s8 NCT6776_ALARM_BITS[]
+	= { 0, 1, 2, 3, 8, 21, 20, 16,		/* in0.. in7 */
+	    17, -1, -1, -1, -1, -1, -1,		/* in8..in14 */
+	    -1,					/* unused */
+	    6, 7, 11, 10, 23,			/* fan1..fan5 */
+	    -1, -1, -1,				/* unused */
+	    4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	    12, 9 };				/* intrusion0, intrusion1 */
+
+static const s8 NCT6779_ALARM_BITS[]
+	= { 0, 1, 2, 3, 8, 21, 20, 16,		/* in0.. in7 */
+	    17, 24, 25, 26, 27, 28, 29,		/* in8..in14 */
+	    -1,					/* unused */
+	    6, 7, 11, 10, 23,			/* fan1..fan5 */
+	    -1, -1, -1,				/* unused */
+	    4, 5, 13, -1, -1, -1,		/* temp1..temp6 */
+	    12, 9 };				/* intrusion0, intrusion1 */
+
+#define FAN_ALARM_BASE		16
+#define TEMP_ALARM_BASE		24
+#define INTRUSION_ALARM_BASE	30
+
+static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };
+static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };
+
+/* DC or PWM output fan configuration */
+static const u8 NCT6775_REG_PWM_MODE[] = { 0x04, 0x04, 0x12 };
+static const u8 NCT6775_PWM_MODE_MASK[] = { 0x01, 0x02, 0x01 };
+
+static const u8 NCT6776_REG_PWM_MODE[] = { 0x04, 0, 0 };
+static const u8 NCT6776_PWM_MODE_MASK[] = { 0x01, 0, 0 };
+
+/* Advanced Fan control, some values are common for all fans */
+
+static const u16 NCT6775_REG_FAN_PULSES[] = { 0x641, 0x642, 0x643, 0x644, 0 };
+static const u16 NCT6776_REG_FAN_PULSES[] = { 0x644, 0x645, 0x646, 0, 0 };
+static const u16 NCT6779_REG_FAN_PULSES[]
+	= { 0x644, 0x645, 0x646, 0x647, 0x648 };
+
+static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301, 0x801, 0x901 };
+static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302, 0x802, 0x902 };
+static const u16 NCT6775_REG_FAN_STEP_DOWN_TIME[] = {
+	0x103, 0x203, 0x303, 0x803, 0x903 };
+static const u16 NCT6775_REG_FAN_STEP_UP_TIME[] = {
+	0x104, 0x204, 0x304, 0x804, 0x904 };
+static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = {
+	0x105, 0x205, 0x305, 0x805, 0x905 };
+static const u16 NCT6775_REG_FAN_START_OUTPUT[]
+	= { 0x106, 0x206, 0x306, 0x806, 0x906 };
+static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
+static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
+
+static const u16 NCT6775_REG_FAN_STOP_TIME[]
+	= { 0x107, 0x207, 0x307, 0x807, 0x907 };
+static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309, 0x809, 0x909 };
+static const u16 NCT6775_REG_PWM_READ[] = { 0x01, 0x03, 0x11, 0x13, 0x15 };
+
+static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
+static const u16 NCT6775_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d };
+
+static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642};
+
+static const u16 NCT6779_REG_FAN[] = { 0x4b0, 0x4b2, 0x4b4, 0x4b6, 0x4b8 };
+
+static const u16 NCT6779_REG_TOLERANCE_H[]
+	= { 0x10c, 0x20c, 0x30c, 0x80c, 0x90c };
+
+static const u16 NCT6775_REG_TEMP[]
+	= { 0x27, 0x150, 0x250, 0x62b, 0x62c, 0x62d };
+static const u16 NCT6779_REG_TEMP[] = { 0x27, 0x150 };
+
+static const u16 NCT6775_REG_TEMP_CONFIG[]
+	= { 0, 0x152, 0x252, 0x628, 0x629, 0x62A };
+static const u16 NCT6775_REG_TEMP_HYST[]
+	= { 0x3a, 0x153, 0x253, 0x673, 0x678, 0x67D };
+static const u16 NCT6775_REG_TEMP_OVER[]
+	= { 0x39, 0x155, 0x255, 0x672, 0x677, 0x67C };
+
+static const u16 NCT6779_REG_TEMP_HYST[]
+	= { 0x3a, 0x153, 0, 0, 0, 0 };
+static const u16 NCT6779_REG_TEMP_OVER[]
+	= { 0x39, 0x155, 0, 0, 0, 0 };
+
+static const u16 NCT6775_REG_TEMP_SOURCE[]
+	= { 0x621, 0x622, 0x623, 0x624, 0x625, 0x626 };
+
+static const u16 NCT6775_REG_TEMP_SEL[]
+	= { 0x100, 0x200, 0x300, 0x800, 0x900 };
+
+static const u16 NCT6775_REG_WEIGHT_TEMP_SEL[]
+	= { 0x139, 0x239, 0x339, 0x839, 0x939 };
+static const u16 NCT6775_REG_WEIGHT_TEMP_STEP[]
+	= { 0x13a, 0x23a, 0x33a, 0x83a, 0x93a };
+static const u16 NCT6775_REG_WEIGHT_TEMP_STEP_TOL[]
+	= { 0x13b, 0x23b, 0x33b, 0x83b, 0x93b };
+static const u16 NCT6775_REG_WEIGHT_DUTY_STEP[]
+	= { 0x13c, 0x23c, 0x33c, 0x83c, 0x93c };
+static const u16 NCT6775_REG_WEIGHT_TEMP_BASE[]
+	= { 0x13d, 0x23d, 0x33d, 0x83d, 0x93d };
+
+static const u16 NCT6776_REG_WEIGHT_DUTY_BASE[]
+	= { 0x13e, 0x23e, 0x33e, 0x83e, 0x93e };
+
+static const u16 NCT6775_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 };
+
+static const u16 NCT6779_REG_TEMP_OFFSET[]
+	= { 0x454, 0x455, 0x456, 0x44a, 0x44b, 0x44c };
+
+static const u16 NCT6776_REG_TEMP_CONFIG[11]
+	= { 0x18, 0x152, 0x252, 0x628, 0x629, 0x62A };
+
+static const u16 NCT6779_REG_TEMP_CONFIG[11] = { 0x18, 0x152 };
+
+static const u16 NCT6775_REG_TEMP_MON[] = { 0x73, 0x75, 0x77, 0x79, 0x7b };
+
+static const u16 NCT6775_REG_AUTO_TEMP[]
+	= { 0x121, 0x221, 0x321, 0x821, 0x921 };
+static const u16 NCT6775_REG_AUTO_PWM[]
+	= { 0x127, 0x227, 0x327, 0x827, 0x927 };
+
+#define NCT6775_AUTO_TEMP(data, nr, p)	((data)->REG_AUTO_TEMP[nr] + (p))
+#define NCT6775_AUTO_PWM(data, nr, p)	((data)->REG_AUTO_PWM[nr] + (p))
+
+static const u16 NCT6775_REG_CRITICAL_ENAB[] = { 0x134, 0x234, 0x334 };
+
+static const u16 NCT6775_REG_CRITICAL_TEMP[] = {
+	0x135, 0x235, 0x335, 0x835, 0x935 };
+static const u16 NCT6775_REG_CRITICAL_TEMP_TOLERANCE[] = {
+	0x138, 0x238, 0x338, 0x838, 0x938 };
+
+static const u16 NCT6779_REG_CRITICAL_PWM_ENABLE[] = {
+	0x136, 0x236, 0x336, 0x836, 0x936 };
+static const u16 NCT6779_REG_CRITICAL_PWM[] = {
+	0x137, 0x237, 0x337, 0x837, 0x937 };
+
+static const char *const nct6775_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"AMD SB-TSI",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PECI Agent 2",
+	"PECI Agent 3",
+	"PECI Agent 4",
+	"PECI Agent 5",
+	"PECI Agent 6",
+	"PECI Agent 7",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP"
+};
+
+static const char *const nct6776_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"SMBUSMASTER 0",
+	"SMBUSMASTER 1",
+	"SMBUSMASTER 2",
+	"SMBUSMASTER 3",
+	"SMBUSMASTER 4",
+	"SMBUSMASTER 5",
+	"SMBUSMASTER 6",
+	"SMBUSMASTER 7",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP",
+	"BYTE_TEMP"
+};
+
+static const char *const nct6779_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN0",
+	"AUXTIN1",
+	"AUXTIN2",
+	"AUXTIN3",
+	"",
+	"SMBUSMASTER 0",
+	"SMBUSMASTER 1",
+	"SMBUSMASTER 2",
+	"SMBUSMASTER 3",
+	"SMBUSMASTER 4",
+	"SMBUSMASTER 5",
+	"SMBUSMASTER 6",
+	"SMBUSMASTER 7",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP",
+	"BYTE_TEMP"
+};
+
+static const u16 NCT6775_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6775_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x661, 0x662, 0x664 };
+
+static const u16 NCT6776_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6776_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x401, 0x402, 0x404 };
+
+static const u16 NCT6779_REG_TEMP_ALTERNATE[ARRAY_SIZE(nct6779_temp_label) - 1]
+	= { 0x490, 0x491, 0x492, 0x493, 0x494, 0x495, 0, 0,
+	    0, 0, 0, 0, 0, 0, 0, 0,
+	    0, 0x400, 0x401, 0x402, 0x404, 0x405, 0x406, 0x407,
+	    0x408, 0 };
+
+static const u16 NCT6775_REG_TEMP_CRIT[ARRAY_SIZE(nct6775_temp_label) - 1]
+	= { 0, 0, 0, 0, 0xa00, 0xa01, 0xa02, 0xa03, 0xa04, 0xa05, 0xa06,
+	    0xa07 };
+
+static const u16 NCT6776_REG_TEMP_CRIT[ARRAY_SIZE(nct6776_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
+
+static const u16 NCT6779_REG_TEMP_CRIT[ARRAY_SIZE(nct6779_temp_label) - 1]
+	= { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x709, 0x70a };
+
+#define NUM_TEMP	10	/* Max number of temp attribute sets w/ limits*/
+#define NUM_TEMP_FIXED	6	/* Max number of fixed temp attribute sets */
+
+static inline int reg_to_pwm_enable(int pwm, int mode)
+{
+	if (mode == 0 && pwm == 255)
+		return 0;	/* off	*/
+	return mode + 1;
+}
+
+static inline int pwm_enable_to_reg(int mode)
+{
+	if (mode == 0)
+		return 0;
+	return mode - 1;
+}
+
+/*
+ * Conversions
+ */
+
+/* 1 is DC mode, output in ms */
+static inline unsigned int step_time_from_reg(u8 reg, u8 mode)
+{
+	return mode ? 400 * reg : 100 * reg;
+}
+
+static inline u8 step_time_to_reg(unsigned int msec, u8 mode)
+{
+	return SENSORS_LIMIT((mode ? (msec + 200) / 400 :
+					(msec + 50) / 100), 1, 255);
+}
+
+static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
+{
+	if (reg == 0 || reg == 255)
+		return 0;
+	return 1350000U / (reg << divreg);
+}
+
+static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
+{
+	if ((reg & 0xff1f) == 0xff1f)
+		return 0;
+
+	reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
+
+	if (reg == 0)
+		return 0;
+
+	return 1350000U / reg;
+}
+
+static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
+{
+	if (reg == 0 || reg == 0xffff)
+		return 0;
+
+	/*
+	 * Even though the registers are 16 bit wide, the fan divisor
+	 * still applies.
+	 */
+	return 1350000U / (reg << divreg);
+}
+
+static inline unsigned int
+div_from_reg(u8 reg)
+{
+	return 1 << reg;
+}
+
+/*
+ * Some of the voltage inputs have internal scaling, the tables below
+ * contain 8 (the ADC LSB in mV) * scaling factor * 100
+ */
+static const u16 scale_in[15] = {
+	800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800, 800, 800, 800,
+	800, 800
+};
+
+static inline long in_from_reg(u8 reg, u8 nr)
+{
+	return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100);
+}
+
+static inline u8 in_to_reg(u32 val, u8 nr)
+{
+	return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0,
+			     255);
+}
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct nct6775_data {
+	int addr;	/* IO base of hw monitor block */
+	enum kinds kind;
+	const char *name;
+
+	struct device *hwmon_dev;
+	struct mutex lock;
+
+	u16 reg_temp[4][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst,
+				    * 3=temp_crit
+				    */
+	u8 temp_src[NUM_TEMP];
+	u16 reg_temp_config[NUM_TEMP];
+	const char * const *temp_label;
+	int temp_label_num;
+
+	u16 REG_CONFIG;
+	u16 REG_VBAT;
+	u16 REG_DIODE;
+
+	const s8 *ALARM_BITS;
+
+	const u16 *REG_VIN;
+	const u16 *REG_IN_MINMAX[2];
+
+	const u16 *REG_TARGET;
+	const u16 *REG_FAN;
+	const u16 *REG_FAN_MODE;
+	const u16 *REG_FAN_MIN;
+	const u16 *REG_FAN_TIME[3];
+
+	const u8 *REG_PWM_MODE;
+	const u8 *PWM_MODE_MASK;
+
+	const u16 *REG_PWM[7];	/* [0]=pwm, [1]=start_output, [2]=stop_output,
+				 * [3]=max_output, [4]=step_output,
+				 * [5]=weight_duty_step, [6]=weight_duty_base
+				 */
+	const u16 *REG_PWM_READ;
+
+	const u16 *REG_TEMP_MON;
+	const u16 *REG_AUTO_TEMP;
+	const u16 *REG_AUTO_PWM;
+
+	const u16 *REG_CRITICAL_TEMP;
+	const u16 *REG_CRITICAL_TEMP_TOLERANCE;
+
+	const u16 *REG_TEMP_SOURCE;	/* temp register sources */
+	const u16 *REG_TEMP_SEL[2];	/* pwm temp, 0=base, 1=weight */
+
+	const u16 *REG_WEIGHT_TEMP[3];	/* 0=base, 1=hyst, 2=step */
+
+	const u16 *REG_TEMP_OFFSET;
+
+	const u16 *REG_ALARM;
+
+	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
+	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
+
+	struct mutex update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* Register values */
+	u8 bank;		/* current register bank */
+	u8 in_num;		/* number of in inputs we have */
+	u8 in[15][3];		/* [0]=in, [1]=in_max, [2]=in_min */
+	unsigned int rpm[5];
+	u16 fan_min[5];
+	u8 fan_div[5];
+	u8 has_pwm;
+	u8 has_fan;		/* some fan inputs can be disabled */
+	u8 has_fan_min;		/* some fans don't have min register */
+	bool has_fan_div;
+
+	u8 temp_fixed_num;	/* 3 or 6 */
+	u8 temp_type[NUM_TEMP_FIXED];
+	s8 temp_offset[NUM_TEMP_FIXED];
+	s16 temp[3][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst */
+	u64 alarms;
+
+	u8 pwm_num;	/* number of pwm */
+
+	u8 pwm_mode[5]; /* 1->DC variable voltage, 0->PWM variable duty cycle */
+	u8 pwm_enable[5]; /* 0->off
+			   * 1->manual
+			   * 2->thermal cruise mode (also called SmartFan I)
+			   * 3->fan speed cruise mode
+			   * 4->SmartFan III
+			   * 5->enhanced variable thermal cruise (SmartFan IV)
+			   */
+	u8 pwm[7][5];	/* [0]=pwm, [1]=start_output, [2]=stop_output,
+			 * [3]=max_output, [4]=step_output,
+			 * [5]=weight_duty_step, [6]=weight_duty_base
+			 */
+	u8 target_temp[5];
+	s16 pwm_temp[5];
+	u8 tolerance[5][2];
+
+	u8 fan_time[3][5]; /* 0 = stop_time, 1 = step_up, 2 = step_down */
+
+	/* Automatic fan speed control registers */
+	int auto_pwm_num;
+	u8 auto_pwm[5][7];
+	u8 auto_temp[5][7];
+
+	u8 pwm_temp_sel[2][5];
+
+	bool pwm_sel_enable[2][5];/* 0->stop_val, 1->weight;
+				   * false->off, true->on
+				   */
+	u8 weight_temp[3][5];	/* 0->temp_step, 1->temp_step_tol,
+				 * 2->temp_base
+				 */
+
+	u8 vid;
+	u8 vrm;
+
+	u16 have_temp;
+	u16 have_temp_fixed;
+	u16 have_in;
+};
+
+struct nct6775_sio_data {
+	int sioreg;
+	enum kinds kind;
+};
+
+static bool is_word_sized(struct nct6775_data *data, u16 reg)
+{
+	switch (data->kind) {
+	case nct6775:
+		return (((reg & 0xff00) == 0x100 ||
+		    (reg & 0xff00) == 0x200) &&
+		   ((reg & 0x00ff) == 0x50 ||
+		    (reg & 0x00ff) == 0x53 ||
+		    (reg & 0x00ff) == 0x55)) ||
+		  (reg & 0xfff0) == 0x630 ||
+		  reg == 0x640 || reg == 0x642 ||
+		  reg == 0x662 ||
+		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
+		  reg == 0x73 || reg == 0x75 || reg == 0x77;
+	case nct6776:
+		return (((reg & 0xff00) == 0x100 ||
+		    (reg & 0xff00) == 0x200) &&
+		   ((reg & 0x00ff) == 0x50 ||
+		    (reg & 0x00ff) == 0x53 ||
+		    (reg & 0x00ff) == 0x55)) ||
+		  (reg & 0xfff0) == 0x630 ||
+		  reg == 0x402 ||
+		  reg == 0x640 || reg == 0x642 ||
+		  ((reg & 0xfff0) == 0x650 && (reg & 0x000f) >= 0x06) ||
+		  reg == 0x73 || reg == 0x75 || reg == 0x77;
+	case nct6779:
+		return reg == 0x150 || reg == 0x153 || reg == 0x155 ||
+		  ((reg & 0xfff0) == 0x4b0 && (reg & 0x000f) < 0x09) ||
+		  reg == 0x402 ||
+		  reg == 0x63a || reg == 0x63c || reg == 0x63e ||
+		  reg == 0x640 || reg == 0x642 ||
+		  reg == 0x73 || reg == 0x75 || reg == 0x77 || reg == 0x79 ||
+		  reg == 0x7b;
+	}
+	return false;
+}
+
+/*
+ * On older chips, only registers 0x50-0x5f are banked.
+ * On more recent chips, all registers are banked.
+ * Assume that is the case and set the bank number for each access.
+ * Cache the bank number so it only needs to be set if it changes.
+ */
+static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)
+{
+	u8 bank = reg >> 8;
+	if (data->bank != bank) {
+		outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);
+		outb_p(bank, data->addr + DATA_REG_OFFSET);
+		data->bank = bank;
+	}
+}
+
+static u16 nct6775_read_value(struct nct6775_data *data, u16 reg)
+{
+	int res, word_sized = is_word_sized(data, reg);
+
+	mutex_lock(&data->lock);
+
+	nct6775_set_bank(data, reg);
+	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
+	res = inb_p(data->addr + DATA_REG_OFFSET);
+	if (word_sized) {
+		outb_p((reg & 0xff) + 1,
+		       data->addr + ADDR_REG_OFFSET);
+		res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
+	}
+
+	mutex_unlock(&data->lock);
+	return res;
+}
+
+static int nct6775_write_value(struct nct6775_data *data, u16 reg, u16 value)
+{
+	int word_sized = is_word_sized(data, reg);
+
+	mutex_lock(&data->lock);
+
+	nct6775_set_bank(data, reg);
+	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
+	if (word_sized) {
+		outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
+		outb_p((reg & 0xff) + 1,
+		       data->addr + ADDR_REG_OFFSET);
+	}
+	outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
+
+	mutex_unlock(&data->lock);
+	return 0;
+}
+
+/* We left-align 8-bit temperature values to make the code simpler */
+static u16 nct6775_read_temp(struct nct6775_data *data, u16 reg)
+{
+	u16 res;
+
+	res = nct6775_read_value(data, reg);
+	if (!is_word_sized(data, reg))
+		res <<= 8;
+
+	return res;
+}
+
+static int nct6775_write_temp(struct nct6775_data *data, u16 reg, u16 value)
+{
+	if (!is_word_sized(data, reg))
+		value >>= 8;
+	return nct6775_write_value(data, reg, value);
+}
+
+/* This function assumes that the caller holds data->update_lock */
+static void nct6775_write_fan_div(struct nct6775_data *data, int nr)
+{
+	u8 reg;
+
+	switch (nr) {
+	case 0:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
+		    | (data->fan_div[0] & 0x7);
+		nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
+		break;
+	case 1:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
+		    | ((data->fan_div[1] << 4) & 0x70);
+		nct6775_write_value(data, NCT6775_REG_FANDIV1, reg);
+	case 2:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
+		    | (data->fan_div[2] & 0x7);
+		nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	case 3:
+		reg = (nct6775_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
+		    | ((data->fan_div[3] << 4) & 0x70);
+		nct6775_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	}
+}
+
+static void nct6775_write_fan_div_common(struct device *dev,
+					 struct nct6775_data *data, int nr)
+{
+	if (data->kind == nct6775)
+		nct6775_write_fan_div(data, nr);
+}
+
+static void nct6775_update_fan_div(struct nct6775_data *data)
+{
+	u8 i;
+
+	i = nct6775_read_value(data, NCT6775_REG_FANDIV1);
+	data->fan_div[0] = i & 0x7;
+	data->fan_div[1] = (i & 0x70) >> 4;
+	i = nct6775_read_value(data, NCT6775_REG_FANDIV2);
+	data->fan_div[2] = i & 0x7;
+	if (data->has_fan & (1<<3))
+		data->fan_div[3] = (i & 0x70) >> 4;
+}
+
+static void nct6775_update_fan_div_common(struct device *dev,
+					  struct nct6775_data *data)
+{
+	if (data->kind == nct6775)
+		nct6775_update_fan_div(data);
+}
+
+static void nct6775_update_pwm(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int i, j;
+	int fanmodecfg, reg;
+	bool duty_is_dc;
+
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+
+		duty_is_dc = data->REG_PWM_MODE[i] &&
+		  (nct6775_read_value(data, data->REG_PWM_MODE[i])
+		   & data->PWM_MODE_MASK[i]);
+		data->pwm_mode[i] = duty_is_dc;
+
+		fanmodecfg = nct6775_read_value(data, data->REG_FAN_MODE[i]);
+		for (j = 0; j < ARRAY_SIZE(data->REG_PWM); j++) {
+			if (data->REG_PWM[j] && data->REG_PWM[j][i]) {
+				data->pwm[j][i]
+				  = nct6775_read_value(data,
+						       data->REG_PWM[j][i]);
+			}
+		}
+
+		data->pwm_enable[i] = reg_to_pwm_enable(data->pwm[0][i],
+							(fanmodecfg >> 4) & 7);
+
+		data->tolerance[i][0] = fanmodecfg & 0x0f;
+		if (data->kind == nct6779) {
+			reg = nct6775_read_value(data,
+						 NCT6779_REG_TOLERANCE_H[i]);
+			data->tolerance[i][0] |= (reg & 0x70) >> 1;
+		}
+		data->tolerance[i][1] =
+			nct6775_read_value(data,
+					data->REG_CRITICAL_TEMP_TOLERANCE[i]);
+
+		data->pwm_sel_enable[0][i] =
+			nct6775_read_value(data, data->REG_TEMP_SEL[0][i])
+				& 0x80;
+		data->pwm_sel_enable[1][i] =
+			nct6775_read_value(data, data->REG_TEMP_SEL[1][i])
+				& 0x80;
+
+		/* Weight data */
+		for (j = 0; j < 2; j++) {
+			reg = nct6775_read_value(data,
+						 data->REG_TEMP_SEL[j][i]);
+			data->pwm_temp_sel[j][i] = reg & 0x1f;
+		}
+		/* Weight temp data */
+		for (j = 0; j < 3; j++) {
+			data->weight_temp[j][i]
+			  = nct6775_read_value(data,
+					       data->REG_WEIGHT_TEMP[j][i]);
+		}
+	}
+}
+
+static void nct6775_update_pwm_limits(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int i, j;
+	u8 reg;
+
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+
+		for (j = 0; j < 3; j++) {
+			data->fan_time[j][i] =
+			  nct6775_read_value(data, data->REG_FAN_TIME[j][i]);
+		}
+
+		data->target_temp[i] =
+			nct6775_read_value(data, data->REG_TARGET[i]) &
+					(data->pwm_mode[i] ? 0xff : 0x7f);
+		data->pwm_temp[i] =
+			nct6775_read_value(data, data->REG_TEMP_MON[i]);
+
+		for (j = 0; j < data->auto_pwm_num; j++) {
+			data->auto_pwm[i][j] =
+			  nct6775_read_value(data,
+					     NCT6775_AUTO_PWM(data, i, j));
+			data->auto_temp[i][j] =
+			  nct6775_read_value(data,
+					     NCT6775_AUTO_TEMP(data, i, j));
+		}
+
+		/* critical auto_pwm temperature data */
+		data->auto_temp[i][data->auto_pwm_num] =
+			nct6775_read_value(data, data->REG_CRITICAL_TEMP[i]);
+
+		switch (data->kind) {
+		case nct6775:
+			reg = nct6775_read_value(data,
+						 NCT6775_REG_CRITICAL_ENAB[i]);
+			data->auto_pwm[i][data->auto_pwm_num] =
+						(reg & 0x02) ? 0xff : 0x00;
+			break;
+		case nct6776:
+			data->auto_pwm[i][data->auto_pwm_num] = 0xff;
+			break;
+		case nct6779:
+			reg = nct6775_read_value(data,
+					NCT6779_REG_CRITICAL_PWM_ENABLE[i]);
+			if (reg & 1)
+				data->auto_pwm[i][data->auto_pwm_num] =
+				  nct6775_read_value(data,
+					NCT6779_REG_CRITICAL_PWM[i]);
+			else
+				data->auto_pwm[i][data->auto_pwm_num] = 0xff;
+			break;
+		}
+	}
+}
+
+static struct nct6775_data *nct6775_update_device(struct device *dev)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	int i, j;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ + HZ/2)
+	 || !data->valid) {
+		/* Fan clock dividers */
+		nct6775_update_fan_div_common(dev, data);
+
+		/* Measured voltages and limits */
+		for (i = 0; i < data->in_num; i++) {
+			if (!(data->have_in & (1 << i)))
+				continue;
+
+			data->in[i][0] = nct6775_read_value(data,
+							    data->REG_VIN[i]);
+			data->in[i][1] = nct6775_read_value(data,
+					  data->REG_IN_MINMAX[0][i]);
+			data->in[i][2] = nct6775_read_value(data,
+					  data->REG_IN_MINMAX[1][i]);
+		}
+
+		/* Measured fan speeds and limits */
+		for (i = 0; i < 5; i++) {
+			u16 reg;
+
+			if (!(data->has_fan & (1 << i)))
+				continue;
+
+			reg = nct6775_read_value(data, data->REG_FAN[i]);
+			data->rpm[i] = data->fan_from_reg(reg,
+							  data->fan_div[i]);
+
+			if (data->has_fan_min & (1 << i))
+				data->fan_min[i] = nct6775_read_value(data,
+					   data->REG_FAN_MIN[i]);
+
+			/*
+			 * If we failed to measure the fan speed and clock
+			 * divider can be increased, let's try that for next
+			 * time
+			 */
+			if (data->has_fan_div && (reg >= 0xff || reg == 0x00)
+			    && data->fan_div[i] < 0x07) {
+				dev_dbg(dev,
+					"Increasing fan%d clock divider from %u to %u\n",
+					i + 1, div_from_reg(data->fan_div[i]),
+					div_from_reg(data->fan_div[i] + 1));
+				data->fan_div[i]++;
+				nct6775_write_fan_div_common(dev, data, i);
+				/* Preserve min limit if possible */
+				if ((data->has_fan_min & (1 << i))
+				 && data->fan_min[i] >= 2
+				 && data->fan_min[i] != 255)
+					nct6775_write_value(data,
+						data->REG_FAN_MIN[i],
+						(data->fan_min[i] /= 2));
+			}
+		}
+
+		nct6775_update_pwm(dev);
+		nct6775_update_pwm_limits(dev);
+
+		/* Measured temperatures and limits */
+		for (i = 0; i < NUM_TEMP; i++) {
+			if (!(data->have_temp & (1 << i)))
+				continue;
+			for (j = 0; j < 4; j++) {
+				if (data->reg_temp[j][i])
+					data->temp[j][i]
+					  = nct6775_read_temp(data,
+						data->reg_temp[j][i]);
+			}
+			if (!(data->have_temp_fixed & (1 << i)))
+				continue;
+			data->temp_offset[i]
+			  = nct6775_read_value(data, data->REG_TEMP_OFFSET[i]);
+		}
+
+		data->alarms = 0;
+		for (i = 0; i < 6; i++) {
+			u8 alarm;
+			if (!data->REG_ALARM[i])
+				continue;
+			alarm = nct6775_read_value(data, data->REG_ALARM[i]);
+			data->alarms |= ((u64)alarm) << (i << 3);
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/*
+ * Sysfs callback functions
+ */
+static ssize_t
+show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	return sprintf(buf, "%ld\n", in_from_reg(data->in[nr][index], nr));
+}
+
+static ssize_t
+store_in_reg(struct device *dev, struct device_attribute *attr, const char *buf,
+	     size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	mutex_lock(&data->update_lock);
+	data->in[nr][index] = in_to_reg(val, nr);
+	nct6775_write_value(data, data->REG_IN_MINMAX[index-1][nr],
+			    data->in[nr][index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = data->ALARM_BITS[sattr->index];
+	return sprintf(buf, "%u\n",
+		       (unsigned int)((data->alarms >> nr) & 0x01));
+}
+
+static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in_reg, NULL, 0, 0);
+static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in_reg, NULL, 1, 0);
+static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in_reg, NULL, 2, 0);
+static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in_reg, NULL, 3, 0);
+static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in_reg, NULL, 4, 0);
+static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in_reg, NULL, 5, 0);
+static SENSOR_DEVICE_ATTR_2(in6_input, S_IRUGO, show_in_reg, NULL, 6, 0);
+static SENSOR_DEVICE_ATTR_2(in7_input, S_IRUGO, show_in_reg, NULL, 7, 0);
+static SENSOR_DEVICE_ATTR_2(in8_input, S_IRUGO, show_in_reg, NULL, 8, 0);
+static SENSOR_DEVICE_ATTR_2(in9_input, S_IRUGO, show_in_reg, NULL, 9, 0);
+static SENSOR_DEVICE_ATTR_2(in10_input, S_IRUGO, show_in_reg, NULL, 10, 0);
+static SENSOR_DEVICE_ATTR_2(in11_input, S_IRUGO, show_in_reg, NULL, 11, 0);
+static SENSOR_DEVICE_ATTR_2(in12_input, S_IRUGO, show_in_reg, NULL, 12, 0);
+static SENSOR_DEVICE_ATTR_2(in13_input, S_IRUGO, show_in_reg, NULL, 13, 0);
+static SENSOR_DEVICE_ATTR_2(in14_input, S_IRUGO, show_in_reg, NULL, 14, 0);
+
+static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 8);
+static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 9);
+static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 11);
+static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 12);
+static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 14);
+
+static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 0, 1);
+static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 1, 1);
+static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 2, 1);
+static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 3, 1);
+static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 4, 1);
+static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 5, 1);
+static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 6, 1);
+static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 7, 1);
+static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 8, 1);
+static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 9, 1);
+static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 10, 1);
+static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 11, 1);
+static SENSOR_DEVICE_ATTR_2(in12_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 12, 1);
+static SENSOR_DEVICE_ATTR_2(in13_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 13, 1);
+static SENSOR_DEVICE_ATTR_2(in14_min, S_IWUSR | S_IRUGO, show_in_reg,
+			    store_in_reg, 14, 1);
+
+static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 0, 2);
+static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 1, 2);
+static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 2, 2);
+static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 3, 2);
+static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 4, 2);
+static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 5, 2);
+static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 6, 2);
+static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 7, 2);
+static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 8, 2);
+static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 9, 2);
+static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 10, 2);
+static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 11, 2);
+static SENSOR_DEVICE_ATTR_2(in12_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 12, 2);
+static SENSOR_DEVICE_ATTR_2(in13_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 13, 2);
+static SENSOR_DEVICE_ATTR_2(in14_max, S_IWUSR | S_IRUGO, show_in_reg,
+			  store_in_reg, 14, 2);
+
+static struct attribute *nct6775_attributes_in[15][5] = {
+	{
+		&sensor_dev_attr_in0_input.dev_attr.attr,
+		&sensor_dev_attr_in0_min.dev_attr.attr,
+		&sensor_dev_attr_in0_max.dev_attr.attr,
+		&sensor_dev_attr_in0_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in1_input.dev_attr.attr,
+		&sensor_dev_attr_in1_min.dev_attr.attr,
+		&sensor_dev_attr_in1_max.dev_attr.attr,
+		&sensor_dev_attr_in1_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in2_input.dev_attr.attr,
+		&sensor_dev_attr_in2_min.dev_attr.attr,
+		&sensor_dev_attr_in2_max.dev_attr.attr,
+		&sensor_dev_attr_in2_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in3_input.dev_attr.attr,
+		&sensor_dev_attr_in3_min.dev_attr.attr,
+		&sensor_dev_attr_in3_max.dev_attr.attr,
+		&sensor_dev_attr_in3_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in4_input.dev_attr.attr,
+		&sensor_dev_attr_in4_min.dev_attr.attr,
+		&sensor_dev_attr_in4_max.dev_attr.attr,
+		&sensor_dev_attr_in4_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in5_input.dev_attr.attr,
+		&sensor_dev_attr_in5_min.dev_attr.attr,
+		&sensor_dev_attr_in5_max.dev_attr.attr,
+		&sensor_dev_attr_in5_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in6_input.dev_attr.attr,
+		&sensor_dev_attr_in6_min.dev_attr.attr,
+		&sensor_dev_attr_in6_max.dev_attr.attr,
+		&sensor_dev_attr_in6_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in7_input.dev_attr.attr,
+		&sensor_dev_attr_in7_min.dev_attr.attr,
+		&sensor_dev_attr_in7_max.dev_attr.attr,
+		&sensor_dev_attr_in7_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in8_input.dev_attr.attr,
+		&sensor_dev_attr_in8_min.dev_attr.attr,
+		&sensor_dev_attr_in8_max.dev_attr.attr,
+		&sensor_dev_attr_in8_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in9_input.dev_attr.attr,
+		&sensor_dev_attr_in9_min.dev_attr.attr,
+		&sensor_dev_attr_in9_max.dev_attr.attr,
+		&sensor_dev_attr_in9_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in10_input.dev_attr.attr,
+		&sensor_dev_attr_in10_min.dev_attr.attr,
+		&sensor_dev_attr_in10_max.dev_attr.attr,
+		&sensor_dev_attr_in10_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in11_input.dev_attr.attr,
+		&sensor_dev_attr_in11_min.dev_attr.attr,
+		&sensor_dev_attr_in11_max.dev_attr.attr,
+		&sensor_dev_attr_in11_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in12_input.dev_attr.attr,
+		&sensor_dev_attr_in12_min.dev_attr.attr,
+		&sensor_dev_attr_in12_max.dev_attr.attr,
+		&sensor_dev_attr_in12_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in13_input.dev_attr.attr,
+		&sensor_dev_attr_in13_min.dev_attr.attr,
+		&sensor_dev_attr_in13_max.dev_attr.attr,
+		&sensor_dev_attr_in13_alarm.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_in14_input.dev_attr.attr,
+		&sensor_dev_attr_in14_min.dev_attr.attr,
+		&sensor_dev_attr_in14_max.dev_attr.attr,
+		&sensor_dev_attr_in14_alarm.dev_attr.attr,
+		NULL
+	},
+};
+
+static const struct attribute_group nct6775_group_in[15] = {
+	{ .attrs = nct6775_attributes_in[0] },
+	{ .attrs = nct6775_attributes_in[1] },
+	{ .attrs = nct6775_attributes_in[2] },
+	{ .attrs = nct6775_attributes_in[3] },
+	{ .attrs = nct6775_attributes_in[4] },
+	{ .attrs = nct6775_attributes_in[5] },
+	{ .attrs = nct6775_attributes_in[6] },
+	{ .attrs = nct6775_attributes_in[7] },
+	{ .attrs = nct6775_attributes_in[8] },
+	{ .attrs = nct6775_attributes_in[9] },
+	{ .attrs = nct6775_attributes_in[10] },
+	{ .attrs = nct6775_attributes_in[11] },
+	{ .attrs = nct6775_attributes_in[12] },
+	{ .attrs = nct6775_attributes_in[13] },
+	{ .attrs = nct6775_attributes_in[14] },
+};
+
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%d\n", data->rpm[nr]);
+}
+
+static ssize_t
+show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%d\n",
+		       data->fan_from_reg_min(data->fan_min[nr],
+					      data->fan_div[nr]));
+}
+
+static ssize_t
+show_fan_div(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%u\n", div_from_reg(data->fan_div[nr]));
+}
+
+static ssize_t
+store_fan_min(struct device *dev, struct device_attribute *attr,
+	      const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	unsigned int reg;
+	u8 new_div;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	if (!data->has_fan_div) {
+		/* NCT6776F or NCT6779D; we know this is a 13 bit register */
+		if (!val) {
+			val = 0xff1f;
+		} else {
+			if (val > 1350000U)
+				val = 135000U;
+			val = 1350000U / val;
+			val = (val & 0x1f) | ((val << 3) & 0xff00);
+		}
+		data->fan_min[nr] = val;
+		goto write_min;	/* Leave fan divider alone */
+	}
+	if (!val) {
+		/* No min limit, alarm disabled */
+		data->fan_min[nr] = 255;
+		new_div = data->fan_div[nr]; /* No change */
+		dev_info(dev, "fan%u low limit and alarm disabled\n", nr + 1);
+		goto write_div;
+	}
+	reg = 1350000U / val;
+	if (reg >= 128 * 255) {
+		/*
+		 * Speed below this value cannot possibly be represented,
+		 * even with the highest divider (128)
+		 */
+		data->fan_min[nr] = 254;
+		new_div = 7; /* 128 == (1 << 7) */
+		dev_warn(dev,
+			 "fan%u low limit %lu below minimum %u, set to minimum\n",
+			 nr + 1, val, data->fan_from_reg_min(254, 7));
+	} else if (!reg) {
+		/*
+		 * Speed above this value cannot possibly be represented,
+		 * even with the lowest divider (1)
+		 */
+		data->fan_min[nr] = 1;
+		new_div = 0; /* 1 == (1 << 0) */
+		dev_warn(dev,
+			 "fan%u low limit %lu above maximum %u, set to maximum\n",
+			 nr + 1, val, data->fan_from_reg_min(1, 0));
+	} else {
+		/*
+		 * Automatically pick the best divider, i.e. the one such
+		 * that the min limit will correspond to a register value
+		 * in the 96..192 range
+		 */
+		new_div = 0;
+		while (reg > 192 && new_div < 7) {
+			reg >>= 1;
+			new_div++;
+		}
+		data->fan_min[nr] = reg;
+	}
+
+write_div:
+	/*
+	 * Write both the fan clock divider (if it changed) and the new
+	 * fan min (unconditionally)
+	 */
+	if (new_div != data->fan_div[nr]) {
+		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
+			nr + 1, div_from_reg(data->fan_div[nr]),
+			div_from_reg(new_div));
+		data->fan_div[nr] = new_div;
+		nct6775_write_fan_div_common(dev, data, nr);
+		/* Give the chip time to sample a new speed value */
+		data->last_updated = jiffies;
+	}
+
+write_min:
+	nct6775_write_value(data, data->REG_FAN_MIN[nr], data->fan_min[nr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute sda_fan_input[] = {
+	SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
+	SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
+	SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
+	SENSOR_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3),
+	SENSOR_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4),
+};
+
+static struct sensor_device_attribute sda_fan_alarm[] = {
+	SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE),
+	SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 1),
+	SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 2),
+	SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 3),
+	SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, FAN_ALARM_BASE + 4),
+};
+
+static struct sensor_device_attribute sda_fan_min[] = {
+	SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 0),
+	SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 1),
+	SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 2),
+	SENSOR_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 3),
+	SENSOR_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min,
+		    store_fan_min, 4),
+};
+
+static struct sensor_device_attribute sda_fan_div[] = {
+	SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
+	SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
+	SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
+	SENSOR_ATTR(fan4_div, S_IRUGO, show_fan_div, NULL, 3),
+	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
+};
+
+static ssize_t
+show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
+}
+
+static ssize_t
+show_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->temp[index][nr]));
+}
+
+static ssize_t
+store_temp(struct device *dev, struct device_attribute *attr, const char *buf,
+	   size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	int err;
+	long val;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	mutex_lock(&data->update_lock);
+	data->temp[index][nr] = LM75_TEMP_TO_REG(val);
+	nct6775_write_temp(data, data->reg_temp[index][nr],
+			   data->temp[index][nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", data->temp_offset[sattr->index] * 1000);
+}
+
+static ssize_t
+store_temp_offset(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), -128, 127);
+
+	mutex_lock(&data->update_lock);
+	data->temp_offset[nr] = val;
+	nct6775_write_value(data, data->REG_TEMP_OFFSET[nr], val);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
+}
+
+static ssize_t
+store_temp_type(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u8 vbat, diode, bit;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val != 1 && val != 3 && val != 4)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	data->temp_type[nr] = val;
+	vbat = nct6775_read_value(data, data->REG_VBAT) & ~(0x02 << nr);
+	diode = nct6775_read_value(data, data->REG_DIODE) & ~(0x02 << nr);
+	bit = 0x02 << nr;
+	switch (val) {
+	case 1:	/* CPU diode (diode, current mode) */
+		vbat |= bit;
+		diode |= bit;
+		break;
+	case 3: /* diode, voltage mode */
+		vbat |= bit;
+		break;
+	case 4:	/* thermistor */
+		break;
+	};
+	nct6775_write_value(data, data->REG_VBAT, vbat);
+	nct6775_write_value(data, data->REG_DIODE, diode);
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static struct sensor_device_attribute_2 sda_temp_input[] = {
+	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
+	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, 0),
+	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, 0),
+	SENSOR_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, 0),
+	SENSOR_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, 0),
+	SENSOR_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, 0),
+	SENSOR_ATTR_2(temp7_input, S_IRUGO, show_temp, NULL, 6, 0),
+	SENSOR_ATTR_2(temp8_input, S_IRUGO, show_temp, NULL, 7, 0),
+	SENSOR_ATTR_2(temp9_input, S_IRUGO, show_temp, NULL, 8, 0),
+	SENSOR_ATTR_2(temp10_input, S_IRUGO, show_temp, NULL, 9, 0),
+};
+
+static struct sensor_device_attribute sda_temp_label[] = {
+	SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
+	SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
+	SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
+	SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
+	SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
+	SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
+	SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
+	SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
+	SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
+	SENSOR_ATTR(temp10_label, S_IRUGO, show_temp_label, NULL, 9),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max[] = {
+	SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      0, 1),
+	SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      1, 1),
+	SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      2, 1),
+	SENSOR_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      3, 1),
+	SENSOR_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      4, 1),
+	SENSOR_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      5, 1),
+	SENSOR_ATTR_2(temp7_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      6, 1),
+	SENSOR_ATTR_2(temp8_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      7, 1),
+	SENSOR_ATTR_2(temp9_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      8, 1),
+	SENSOR_ATTR_2(temp10_max, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      9, 1),
+};
+
+static struct sensor_device_attribute_2 sda_temp_max_hyst[] = {
+	SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      0, 2),
+	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      1, 2),
+	SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      2, 2),
+	SENSOR_ATTR_2(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      3, 2),
+	SENSOR_ATTR_2(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      4, 2),
+	SENSOR_ATTR_2(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      5, 2),
+	SENSOR_ATTR_2(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      6, 2),
+	SENSOR_ATTR_2(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      7, 2),
+	SENSOR_ATTR_2(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      8, 2),
+	SENSOR_ATTR_2(temp10_max_hyst, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      9, 2),
+};
+
+static struct sensor_device_attribute_2 sda_temp_crit[] = {
+	SENSOR_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      0, 3),
+	SENSOR_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      1, 3),
+	SENSOR_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      2, 3),
+	SENSOR_ATTR_2(temp4_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      3, 3),
+	SENSOR_ATTR_2(temp5_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      4, 3),
+	SENSOR_ATTR_2(temp6_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      5, 3),
+	SENSOR_ATTR_2(temp7_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      6, 3),
+	SENSOR_ATTR_2(temp8_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      7, 3),
+	SENSOR_ATTR_2(temp9_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      8, 3),
+	SENSOR_ATTR_2(temp10_crit, S_IRUGO | S_IWUSR, show_temp, store_temp,
+		      9, 3),
+};
+
+static struct sensor_device_attribute sda_temp_offset[] = {
+	SENSOR_ATTR(temp1_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 0),
+	SENSOR_ATTR(temp2_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 1),
+	SENSOR_ATTR(temp3_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 2),
+	SENSOR_ATTR(temp4_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 3),
+	SENSOR_ATTR(temp5_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 4),
+	SENSOR_ATTR(temp6_offset, S_IRUGO | S_IWUSR, show_temp_offset,
+		    store_temp_offset, 5),
+};
+
+static struct sensor_device_attribute sda_temp_type[] = {
+	SENSOR_ATTR(temp1_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 0),
+	SENSOR_ATTR(temp2_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 1),
+	SENSOR_ATTR(temp3_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 2),
+	SENSOR_ATTR(temp4_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 3),
+	SENSOR_ATTR(temp5_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 4),
+	SENSOR_ATTR(temp6_type, S_IRUGO | S_IWUSR, show_temp_type,
+		    store_temp_type, 5),
+};
+
+static struct sensor_device_attribute sda_temp_alarm[] = {
+	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE),
+	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 1),
+	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 2),
+	SENSOR_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 3),
+	SENSOR_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 4),
+	SENSOR_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL,
+		    TEMP_ALARM_BASE + 5),
+};
+
+#define NUM_TEMP_ALARM	ARRAY_SIZE(sda_temp_alarm)
+
+static ssize_t
+show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", !data->pwm_mode[sattr->index]);
+}
+
+static ssize_t
+store_pwm_mode(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val > 1)
+		return -EINVAL;
+
+	/* Setting DC mode is not supported for all chips/channels */
+	if (data->REG_PWM_MODE[nr] == 0) {
+		if (val)
+			return -EINVAL;
+		return count;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->pwm_mode[nr] = val;
+	reg = nct6775_read_value(data, data->REG_PWM_MODE[nr]);
+	reg &= ~data->PWM_MODE_MASK[nr];
+	if (val)
+		reg |= data->PWM_MODE_MASK[nr];
+	nct6775_write_value(data, data->REG_PWM_MODE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n", data->pwm_enable[sattr->index]);
+}
+
+static ssize_t
+show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	int pwm;
+
+	/*
+	 * For automatic fan control modes, show current pwm readings.
+	 * Otherwise, show the configured value.
+	 */
+	if (index == 0 && data->pwm_enable[nr] > 1)
+		pwm = nct6775_read_value(data, data->REG_PWM_READ[nr]);
+	else
+		pwm = data->pwm[index][nr];
+
+	return sprintf(buf, "%d\n", pwm);
+}
+
+static ssize_t
+store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,
+	  size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int minval[7] = { 0, 1, 1, data->pwm[2][nr], 0, 0, 0 };
+	int maxval[7]
+	  = { 255, 255, data->pwm[3][nr] ? : 255, 255, 255, 255, 255 };
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	val = SENSORS_LIMIT(val, minval[index], maxval[index]);
+
+	mutex_lock(&data->update_lock);
+	data->pwm[index][nr] = val;
+	nct6775_write_value(data, data->REG_PWM[index][nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* Returns 0 if OK, -EINVAL otherwise */
+static int check_trip_points(struct nct6775_data *data, int nr)
+{
+	int i;
+
+	for (i = 0; i < data->auto_pwm_num - 1; i++) {
+		if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1])
+			return -EINVAL;
+	}
+	for (i = 0; i < data->auto_pwm_num - 1; i++) {
+		if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1])
+			return -EINVAL;
+	}
+	/* validate critical temperature and pwm if enabled (pwm > 0) */
+	if (data->auto_pwm[nr][data->auto_pwm_num]) {
+		if (data->auto_temp[nr][data->auto_pwm_num - 1] >
+				data->auto_temp[nr][data->auto_pwm_num] ||
+		    data->auto_pwm[nr][data->auto_pwm_num - 1] >
+				data->auto_pwm[nr][data->auto_pwm_num])
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static ssize_t
+store_pwm_enable(struct device *dev, struct device_attribute *attr,
+		 const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	unsigned long val;
+	int err;
+	u16 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val > 5)
+		return -EINVAL;
+
+	if (val == 4 && data->kind != nct6775)
+		return -EINVAL;
+
+	if (val == 5 && check_trip_points(data, nr)) {
+		dev_err(dev, "Inconsistent trip points, not switching to SmartFan IV mode\n");
+		dev_err(dev, "Adjust trip points and try again\n");
+		return -EINVAL;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->pwm_enable[nr] = val;
+	if (!val) {
+		/*
+		 * turn off pwm control: select manual mode, set pwm to maximum
+		 */
+		data->pwm[0][nr] = 255;
+		nct6775_write_value(data, data->REG_PWM[0][nr], 255);
+	}
+	reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
+	reg &= 0x0f;
+	reg |= pwm_enable_to_reg(val) << 4;
+	nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_pwm_temp_sel(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int i, src, sel = 0;
+
+	src = data->pwm_temp_sel[sattr->index][sattr->nr];
+
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		if (src == data->temp_src[i]) {
+			sel = i + 1;
+			break;
+		}
+	}
+
+	return sprintf(buf, "%d\n", sel);
+}
+
+static ssize_t
+store_pwm_temp_sel(struct device *dev, struct device_attribute *attr,
+		   const char *buf, size_t count)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err, reg, src;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val == 0 || val > NUM_TEMP)
+		return -EINVAL;
+	if (!(data->have_temp & (1 << (val - 1))) || !data->temp_src[val - 1])
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	src = data->temp_src[val - 1];
+	data->pwm_temp_sel[index][nr] = src;
+	reg = nct6775_read_value(data, data->REG_TEMP_SEL[index][nr]);
+	reg &= 0xe0;
+	reg |= src;
+	nct6775_write_value(data, data->REG_TEMP_SEL[index][nr], reg);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t
+show_target_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+
+	return sprintf(buf, "%d\n",
+		       data->target_temp[sattr->index] * 1000);
+}
+
+static ssize_t
+store_target_temp(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);
+	int nr = sattr->index;
+	long val;
+	int err;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
+
+	mutex_lock(&data->update_lock);
+	data->target_temp[nr] = val;
+	nct6775_write_value(data, data->REG_TARGET[nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_auto_temp_hyst(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index >= data->auto_pwm_num ? 1 : 0;
+	int tolerance = data->tolerance[nr][point];
+	int temp = data->auto_temp[nr][sattr->index];
+
+	return sprintf(buf, "%d\n", (temp - tolerance) * 1000);
+}
+
+static ssize_t
+store_auto_temp_hyst(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index >= data->auto_pwm_num ? 1 : 0;
+	u16 reg;
+	long val;
+	int err;
+	int maxlimit[2][3] = { { 15, 7, 63 }, { 15, 7, 7 } };
+	int mask[] = { 0x0f, 0x07, 0x07 };
+	int temp;
+
+	err = kstrtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	temp = data->auto_temp[nr][sattr->index];
+	val = temp - DIV_ROUND_CLOSEST(val, 1000);
+
+	/* Limit tolerance as needed */
+	val = SENSORS_LIMIT(val, 0, maxlimit[point][data->kind]);
+
+	mutex_lock(&data->update_lock);
+	if (point) {
+		nct6775_write_value(data,
+				    data->REG_CRITICAL_TEMP_TOLERANCE[nr],
+				    val);
+	} else {
+		reg = nct6775_read_value(data, data->REG_FAN_MODE[nr]);
+		reg = (reg & ~mask[nr]) | (val & mask[nr]);
+		nct6775_write_value(data, data->REG_FAN_MODE[nr], reg);
+		if (data->kind == nct6779) {
+			reg = nct6775_read_value(data,
+						 NCT6779_REG_TOLERANCE_H[nr]);
+			reg = (reg & 0x70) | ((val & 0x38) << 1);
+			nct6775_write_value(data,
+					    NCT6779_REG_TOLERANCE_H[nr], reg);
+		}
+	}
+
+	data->tolerance[nr][point] = val;
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 4, 0);
+
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 0);
+static SENSOR_DEVICE_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 1);
+static SENSOR_DEVICE_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 2);
+static SENSOR_DEVICE_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 3);
+static SENSOR_DEVICE_ATTR(pwm5_mode, S_IWUSR | S_IRUGO, show_pwm_mode,
+			  store_pwm_mode, 4);
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 1);
+static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 2);
+static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 3);
+static SENSOR_DEVICE_ATTR(pwm5_enable, S_IWUSR | S_IRUGO, show_pwm_enable,
+			  store_pwm_enable, 4);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 4, 0);
+
+static SENSOR_DEVICE_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 0);
+static SENSOR_DEVICE_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 1);
+static SENSOR_DEVICE_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 2);
+static SENSOR_DEVICE_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 3);
+static SENSOR_DEVICE_ATTR(pwm5_target, S_IWUSR | S_IRUGO, show_target_temp,
+			  store_target_temp, 4);
+
+/* Smart Fan registers */
+
+static ssize_t
+show_pwm_sel_enable(struct device *dev, struct device_attribute *attr,
+		    char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+	return sprintf(buf, "%d\n",
+		       data->pwm_sel_enable[sattr->index][sattr->nr]);
+}
+
+static ssize_t
+store_pwm_sel_enable(struct device *dev, struct device_attribute *attr,
+		     const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (val > 1)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->pwm_sel_enable[index][nr] = val;
+	reg = nct6775_read_value(data, data->REG_TEMP_SEL[index][nr]);
+	reg &= 0x7f;
+	if (val)
+		reg |= 0x80;
+	nct6775_write_value(data, data->REG_TEMP_SEL[index][nr], reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_weight_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n", data->weight_temp[index][nr] * 1000);
+}
+
+static ssize_t
+store_weight_temp(struct device *dev, struct device_attribute *attr,
+		  const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->weight_temp[index][nr] = val;
+	nct6775_write_value(data, data->REG_WEIGHT_TEMP[index][nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(pwm1_stop_output_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_stop_output_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_stop_output_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_stop_output_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_stop_output_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 4, 0);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_enable, S_IWUSR | S_IRUGO,
+			    show_pwm_sel_enable, store_pwm_sel_enable, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_sel, S_IWUSR | S_IRUGO,
+			    show_pwm_temp_sel, store_pwm_temp_sel, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 4, 0);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_tol, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 3, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_temp_step_base, S_IWUSR | S_IRUGO,
+			    show_weight_temp, store_weight_temp, 4, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 0, 5);
+static SENSOR_DEVICE_ATTR_2(pwm2_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 1, 5);
+static SENSOR_DEVICE_ATTR_2(pwm3_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 2, 5);
+static SENSOR_DEVICE_ATTR_2(pwm4_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 3, 5);
+static SENSOR_DEVICE_ATTR_2(pwm5_weight_duty_step, S_IWUSR | S_IRUGO,
+			    show_pwm, store_pwm, 4, 5);
+
+/* duty_base is not supported on all chips */
+static struct sensor_device_attribute_2 sda_weight_duty_base[] = {
+	SENSOR_ATTR_2(pwm1_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 0, 6),
+	SENSOR_ATTR_2(pwm2_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 1, 6),
+	SENSOR_ATTR_2(pwm3_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 2, 6),
+	SENSOR_ATTR_2(pwm4_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 3, 6),
+	SENSOR_ATTR_2(pwm5_weight_duty_base, S_IWUSR | S_IRUGO,
+		      show_pwm, store_pwm, 4, 6),
+};
+
+static ssize_t
+show_fan_time(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+
+	return sprintf(buf, "%d\n",
+		       step_time_from_reg(data->fan_time[index][nr],
+					  data->pwm_mode[nr]));
+}
+
+static ssize_t
+store_fan_time(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int index = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = step_time_to_reg(val, data->pwm_mode[nr]);
+	mutex_lock(&data->update_lock);
+	data->fan_time[index][nr] = val;
+	nct6775_write_value(data, data->REG_FAN_TIME[index][nr], val);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 3, 0);
+static SENSOR_DEVICE_ATTR_2(pwm5_stop_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 4, 0);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_step_up_time, S_IWUSR | S_IRUGO, show_fan_time,
+			    store_fan_time, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 3, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_step_down_time, S_IWUSR | S_IRUGO,
+			    show_fan_time, store_fan_time, 4, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_start_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_start_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_start_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm4_start_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 3, 1);
+static SENSOR_DEVICE_ATTR_2(pwm5_start_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 4, 1);
+
+static SENSOR_DEVICE_ATTR_2(pwm1_stop_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_stop_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_stop_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm4_stop_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 3, 2);
+static SENSOR_DEVICE_ATTR_2(pwm5_stop_output, S_IWUSR | S_IRUGO, show_pwm,
+			    store_pwm, 4, 2);
+
+/* max_output is not supported on all chips */
+static struct sensor_device_attribute_2 sda_max_output[] = {
+	SENSOR_ATTR_2(pwm1_max_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      0, 3),
+	SENSOR_ATTR_2(pwm2_max_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      1, 3),
+	SENSOR_ATTR_2(pwm3_max_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      2, 3),
+	SENSOR_ATTR_2(pwm4_max_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      3, 3),
+	SENSOR_ATTR_2(pwm5_max_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      4, 3),
+};
+
+/* step_output is not supported on all chips */
+static struct sensor_device_attribute_2 sda_step_output[] = {
+	SENSOR_ATTR_2(pwm1_step_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      0, 4),
+	SENSOR_ATTR_2(pwm2_step_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      1, 4),
+	SENSOR_ATTR_2(pwm3_step_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      2, 4),
+	SENSOR_ATTR_2(pwm4_step_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      3, 4),
+	SENSOR_ATTR_2(pwm5_step_output, S_IWUSR | S_IRUGO, show_pwm, store_pwm,
+		      4, 4),
+};
+
+static struct attribute *nct6775_attributes_pwm[5][19] = {
+	{
+		&sensor_dev_attr_pwm1.dev_attr.attr,
+		&sensor_dev_attr_pwm1_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm1_stop_output_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm1_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm1_target.dev_attr.attr,
+		&sensor_dev_attr_pwm1_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm1_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm1_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm1_start_output.dev_attr.attr,
+		&sensor_dev_attr_pwm1_stop_output.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm1_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm2.dev_attr.attr,
+		&sensor_dev_attr_pwm2_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm2_stop_output_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm2_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm2_target.dev_attr.attr,
+		&sensor_dev_attr_pwm2_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm2_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm2_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm2_start_output.dev_attr.attr,
+		&sensor_dev_attr_pwm2_stop_output.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm2_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm3.dev_attr.attr,
+		&sensor_dev_attr_pwm3_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm3_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm3_stop_output_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm3_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm3_target.dev_attr.attr,
+		&sensor_dev_attr_pwm3_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm3_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm3_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm3_start_output.dev_attr.attr,
+		&sensor_dev_attr_pwm3_stop_output.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm3_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm4.dev_attr.attr,
+		&sensor_dev_attr_pwm4_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm4_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm4_stop_output_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm4_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm4_target.dev_attr.attr,
+		&sensor_dev_attr_pwm4_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm4_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm4_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm4_start_output.dev_attr.attr,
+		&sensor_dev_attr_pwm4_stop_output.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm4_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+	{
+		&sensor_dev_attr_pwm5.dev_attr.attr,
+		&sensor_dev_attr_pwm5_mode.dev_attr.attr,
+		&sensor_dev_attr_pwm5_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm5_stop_output_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_enable.dev_attr.attr,
+		&sensor_dev_attr_pwm5_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm5_target.dev_attr.attr,
+		&sensor_dev_attr_pwm5_stop_time.dev_attr.attr,
+		&sensor_dev_attr_pwm5_step_up_time.dev_attr.attr,
+		&sensor_dev_attr_pwm5_step_down_time.dev_attr.attr,
+		&sensor_dev_attr_pwm5_start_output.dev_attr.attr,
+		&sensor_dev_attr_pwm5_stop_output.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_sel.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_step.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_step_tol.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_temp_step_base.dev_attr.attr,
+		&sensor_dev_attr_pwm5_weight_duty_step.dev_attr.attr,
+		NULL
+	},
+};
+
+static const struct attribute_group nct6775_group_pwm[5] = {
+	{ .attrs = nct6775_attributes_pwm[0] },
+	{ .attrs = nct6775_attributes_pwm[1] },
+	{ .attrs = nct6775_attributes_pwm[2] },
+	{ .attrs = nct6775_attributes_pwm[3] },
+	{ .attrs = nct6775_attributes_pwm[4] },
+};
+
+static ssize_t
+show_auto_pwm(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+
+	return sprintf(buf, "%d\n", data->auto_pwm[sattr->nr][sattr->index]);
+}
+
+static ssize_t
+store_auto_pwm(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index;
+	unsigned long val;
+	int err;
+	u8 reg;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+	if (val > 255)
+		return -EINVAL;
+
+	if (point == data->auto_pwm_num) {
+		if (data->kind != nct6775 && !val)
+			return -EINVAL;
+		if (data->kind != nct6779 && val)
+			val = 0xff;
+	}
+
+	mutex_lock(&data->update_lock);
+	data->auto_pwm[nr][point] = val;
+	if (point < data->auto_pwm_num) {
+		nct6775_write_value(data,
+				    NCT6775_AUTO_PWM(data, nr, point),
+				    data->auto_pwm[nr][point]);
+	} else {
+		switch (data->kind) {
+		case nct6775:
+			/* disable if needed (pwm == 0) */
+			reg = nct6775_read_value(data,
+						 NCT6775_REG_CRITICAL_ENAB[nr]);
+			if (val)
+				reg |= 0x02;
+			else
+				reg &= ~0x02;
+			nct6775_write_value(data, NCT6775_REG_CRITICAL_ENAB[nr],
+					    reg);
+			break;
+		case nct6776:
+			break; /* always enabled, nothing to do */
+		case nct6779:
+			nct6775_write_value(data, NCT6779_REG_CRITICAL_PWM[nr],
+					    val);
+			reg = nct6775_read_value(data,
+					NCT6779_REG_CRITICAL_PWM_ENABLE[nr]);
+			if (val == 255)
+				reg &= ~0x01;
+			else
+				reg |= 0x01;
+			nct6775_write_value(data,
+					    NCT6779_REG_CRITICAL_PWM_ENABLE[nr],
+					    reg);
+			break;
+		}
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t
+show_auto_temp(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = nct6775_update_device(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index;
+
+	/*
+	 * We don't know for sure if the temperature is signed or unsigned.
+	 * Assume it is unsigned.
+	 */
+	return sprintf(buf, "%d\n", data->auto_temp[nr][point] * 1000);
+}
+
+static ssize_t
+store_auto_temp(struct device *dev, struct device_attribute *attr,
+		const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);
+	int nr = sattr->nr;
+	int point = sattr->index;
+	unsigned long val;
+	int err;
+
+	err = kstrtoul(buf, 10, &val);
+	if (err)
+		return err;
+	if (val > 255000)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	data->auto_temp[nr][point] = DIV_ROUND_CLOSEST(val, 1000);
+	if (point < data->auto_pwm_num) {
+		nct6775_write_value(data,
+				    NCT6775_AUTO_TEMP(data, nr, point),
+				    data->auto_temp[nr][point]);
+	} else {
+		nct6775_write_value(data, data->REG_CRITICAL_TEMP[nr],
+				    data->auto_temp[nr][point]);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/*
+ * The number of auto-point trip points is chip dependent.
+ * Need to check support while generating/removing attribute files.
+ */
+static struct sensor_device_attribute_2 sda_auto_pwm_arrays[] = {
+	SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 1),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 1),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 1),
+	SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 2),
+	SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 2),
+	SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 2),
+	SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 3),
+	SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 3),
+	SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 3),
+	SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 4),
+	SENSOR_ATTR_2(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 4),
+	SENSOR_ATTR_2(pwm1_auto_point5_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 4),
+	SENSOR_ATTR_2(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 5),
+	SENSOR_ATTR_2(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 5),
+	SENSOR_ATTR_2(pwm1_auto_point6_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 5),
+	SENSOR_ATTR_2(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 0, 6),
+	SENSOR_ATTR_2(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 0, 6),
+	SENSOR_ATTR_2(pwm1_auto_point7_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 0, 6),
+
+	SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 0),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 0),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 0),
+	SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 2),
+	SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 2),
+	SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 2),
+	SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 3),
+	SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 3),
+	SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 3),
+	SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 4),
+	SENSOR_ATTR_2(pwm2_auto_point5_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 4),
+	SENSOR_ATTR_2(pwm2_auto_point5_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 4),
+	SENSOR_ATTR_2(pwm2_auto_point6_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 5),
+	SENSOR_ATTR_2(pwm2_auto_point6_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 5),
+	SENSOR_ATTR_2(pwm2_auto_point6_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 5),
+	SENSOR_ATTR_2(pwm2_auto_point7_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 1, 6),
+	SENSOR_ATTR_2(pwm2_auto_point7_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 1, 6),
+	SENSOR_ATTR_2(pwm2_auto_point7_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 1, 6),
+
+	SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 0),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 0),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 0),
+	SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 1),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 1),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 1),
+	SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 2),
+	SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 2),
+	SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 2),
+	SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 3),
+	SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 3),
+	SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 3),
+	SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 4),
+	SENSOR_ATTR_2(pwm3_auto_point5_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 4),
+	SENSOR_ATTR_2(pwm3_auto_point5_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 4),
+	SENSOR_ATTR_2(pwm3_auto_point6_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 5),
+	SENSOR_ATTR_2(pwm3_auto_point6_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 5),
+	SENSOR_ATTR_2(pwm3_auto_point6_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 5),
+	SENSOR_ATTR_2(pwm3_auto_point7_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 2, 6),
+	SENSOR_ATTR_2(pwm3_auto_point7_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 2, 6),
+	SENSOR_ATTR_2(pwm3_auto_point7_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 2, 6),
+
+	SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 0),
+	SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 0),
+	SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 0),
+	SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 1),
+	SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 1),
+	SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 1),
+	SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 2),
+	SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 2),
+	SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 2),
+	SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 3),
+	SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 3),
+	SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 3),
+	SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 4),
+	SENSOR_ATTR_2(pwm4_auto_point5_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 4),
+	SENSOR_ATTR_2(pwm4_auto_point5_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 4),
+	SENSOR_ATTR_2(pwm4_auto_point6_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 5),
+	SENSOR_ATTR_2(pwm4_auto_point6_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 5),
+	SENSOR_ATTR_2(pwm4_auto_point6_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 5),
+	SENSOR_ATTR_2(pwm4_auto_point7_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 3, 6),
+	SENSOR_ATTR_2(pwm4_auto_point7_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 3, 6),
+	SENSOR_ATTR_2(pwm4_auto_point7_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 3, 6),
+
+	SENSOR_ATTR_2(pwm5_auto_point1_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 0),
+	SENSOR_ATTR_2(pwm5_auto_point1_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 0),
+	SENSOR_ATTR_2(pwm5_auto_point1_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 0),
+	SENSOR_ATTR_2(pwm5_auto_point2_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 1),
+	SENSOR_ATTR_2(pwm5_auto_point2_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 1),
+	SENSOR_ATTR_2(pwm5_auto_point2_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 1),
+	SENSOR_ATTR_2(pwm5_auto_point3_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 2),
+	SENSOR_ATTR_2(pwm5_auto_point3_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 2),
+	SENSOR_ATTR_2(pwm5_auto_point3_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 2),
+	SENSOR_ATTR_2(pwm5_auto_point4_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 3),
+	SENSOR_ATTR_2(pwm5_auto_point4_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 3),
+	SENSOR_ATTR_2(pwm5_auto_point4_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 3),
+	SENSOR_ATTR_2(pwm5_auto_point5_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 4),
+	SENSOR_ATTR_2(pwm5_auto_point5_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 4),
+	SENSOR_ATTR_2(pwm5_auto_point5_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 4),
+	SENSOR_ATTR_2(pwm5_auto_point6_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 5),
+	SENSOR_ATTR_2(pwm5_auto_point6_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 5),
+	SENSOR_ATTR_2(pwm5_auto_point6_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 5),
+	SENSOR_ATTR_2(pwm5_auto_point7_pwm, S_IWUSR | S_IRUGO,
+			  show_auto_pwm, store_auto_pwm, 4, 6),
+	SENSOR_ATTR_2(pwm5_auto_point7_temp, S_IWUSR | S_IRUGO,
+			  show_auto_temp, store_auto_temp, 4, 6),
+	SENSOR_ATTR_2(pwm5_auto_point7_temp_hyst, S_IWUSR | S_IRUGO,
+			  show_auto_temp_hyst, store_auto_temp_hyst, 4, 6),
+};
+
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+/* Case open detection */
+
+static ssize_t
+clear_caseopen(struct device *dev, struct device_attribute *attr,
+	       const char *buf, size_t count)
+{
+	struct nct6775_data *data = dev_get_drvdata(dev);
+	struct nct6775_sio_data *sio_data = dev->platform_data;
+	int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;
+	unsigned long val;
+	u8 reg;
+
+	if (kstrtoul(buf, 10, &val) || val != 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+
+	/*
+	 * Use CR registers to clear caseopen status.
+	 * The CR registers are the same for all chips, and not all chips
+	 * support clearing the caseopen status through "regular" registers.
+	 */
+	superio_enter(sio_data->sioreg);
+	superio_select(sio_data->sioreg, NCT6775_LD_ACPI);
+	reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]);
+	reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];
+	superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
+	reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];
+	superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);
+	superio_exit(sio_data->sioreg);
+
+	data->valid = 0;	/* Force cache refresh */
+
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static struct sensor_device_attribute sda_caseopen[] = {
+	SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm,
+		    clear_caseopen, INTRUSION_ALARM_BASE),
+	SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm,
+		    clear_caseopen, INTRUSION_ALARM_BASE + 1),
+};
+
+/*
+ * Driver and device management
+ */
+
+static void nct6775_device_remove_files(struct device *dev)
+{
+	/*
+	 * some entries in the following arrays may not have been used in
+	 * device_create_file(), but device_remove_file() will ignore them
+	 */
+	int i;
+	struct nct6775_data *data = dev_get_drvdata(dev);
+
+	for (i = 0; i < data->pwm_num; i++)
+		sysfs_remove_group(&dev->kobj, &nct6775_group_pwm[i]);
+
+	for (i = 0; i < ARRAY_SIZE(sda_max_output); i++)
+		device_remove_file(dev, &sda_max_output[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_step_output); i++)
+		device_remove_file(dev, &sda_max_output[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_weight_duty_base); i++)
+		device_remove_file(dev, &sda_weight_duty_base[i].dev_attr);
+
+	for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++)
+		device_remove_file(dev, &sda_auto_pwm_arrays[i].dev_attr);
+
+	for (i = 0; i < data->in_num; i++)
+		sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]);
+
+	for (i = 0; i < 5; i++) {
+		device_remove_file(dev, &sda_fan_input[i].dev_attr);
+		device_remove_file(dev, &sda_fan_alarm[i].dev_attr);
+		device_remove_file(dev, &sda_fan_div[i].dev_attr);
+		device_remove_file(dev, &sda_fan_min[i].dev_attr);
+	}
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		device_remove_file(dev, &sda_temp_input[i].dev_attr);
+		device_remove_file(dev, &sda_temp_label[i].dev_attr);
+		device_remove_file(dev, &sda_temp_max[i].dev_attr);
+		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
+		device_remove_file(dev, &sda_temp_crit[i].dev_attr);
+		if (!(data->have_temp_fixed & (1 << i)))
+			continue;
+		device_remove_file(dev, &sda_temp_type[i].dev_attr);
+		device_remove_file(dev, &sda_temp_offset[i].dev_attr);
+		if (i >= NUM_TEMP_ALARM)
+			continue;
+		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
+	}
+
+	device_remove_file(dev, &sda_caseopen[0].dev_attr);
+	device_remove_file(dev, &sda_caseopen[1].dev_attr);
+
+	device_remove_file(dev, &dev_attr_name);
+	device_remove_file(dev, &dev_attr_cpu0_vid);
+}
+
+/* Get the monitoring functions started */
+static inline void __devinit nct6775_init_device(struct nct6775_data *data)
+{
+	int i;
+	u8 tmp, diode;
+
+	/* Start monitoring if needed */
+	if (data->REG_CONFIG) {
+		tmp = nct6775_read_value(data, data->REG_CONFIG);
+		if (!(tmp & 0x01))
+			nct6775_write_value(data, data->REG_CONFIG, tmp | 0x01);
+	}
+
+	/* Enable temperature sensors if needed */
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		if (!data->reg_temp_config[i])
+			continue;
+		tmp = nct6775_read_value(data, data->reg_temp_config[i]);
+		if (tmp & 0x01)
+			nct6775_write_value(data, data->reg_temp_config[i],
+					    tmp & 0xfe);
+	}
+
+	/* Enable VBAT monitoring if needed */
+	tmp = nct6775_read_value(data, data->REG_VBAT);
+	if (!(tmp & 0x01))
+		nct6775_write_value(data, data->REG_VBAT, tmp | 0x01);
+
+	diode = nct6775_read_value(data, data->REG_DIODE);
+
+	for (i = 0; i < data->temp_fixed_num; i++) {
+		if (!(data->have_temp_fixed & (1 << i)))
+			continue;
+		if ((tmp & (0x02 << i)))	/* diode */
+			data->temp_type[i] = 3 - ((diode >> i) & 0x02);
+		else				/* thermistor */
+			data->temp_type[i] = 4;
+	}
+}
+
+static void __devinit
+nct6775_check_fan_inputs(const struct nct6775_sio_data *sio_data,
+			 struct nct6775_data *data)
+{
+	int regval;
+	bool fan3pin, fan3min, fan4pin, fan4min, fan5pin;
+	bool pwm3pin, pwm4pin, pwm5pin;
+
+	superio_enter(sio_data->sioreg);
+
+	/* fan4 and fan5 share some pins with the GPIO and serial flash */
+	if (data->kind == nct6775) {
+		regval = superio_inb(sio_data->sioreg, 0x2c);
+
+		fan3pin = regval & (1 << 6);
+		fan3min = fan3pin;
+		pwm3pin = regval & (1 << 7);
+
+		/* On NCT6775, fan4 shares pins with the fdc interface */
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
+		fan4min = 0;
+		fan5pin = 0;
+		pwm4pin = 0;
+		pwm5pin = 0;
+	} else if (data->kind == nct6776) {
+		bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80;
+
+		superio_select(sio_data->sioreg, NCT6775_LD_HWM);
+		regval = superio_inb(sio_data->sioreg, SIO_REG_ENABLE);
+
+		if (regval & 0x80)
+			fan3pin = gpok;
+		else
+			fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+
+		if (regval & 0x40)
+			fan4pin = gpok;
+		else
+			fan4pin = superio_inb(sio_data->sioreg, 0x1C) & 0x01;
+
+		if (regval & 0x20)
+			fan5pin = gpok;
+		else
+			fan5pin = superio_inb(sio_data->sioreg, 0x1C) & 0x02;
+
+		fan4min = fan4pin;
+		fan3min = fan3pin;
+		pwm3pin = fan3pin;
+		pwm4pin = 0;
+		pwm5pin = 0;
+	} else {	/* NCT6779D */
+		regval = superio_inb(sio_data->sioreg, 0x1c);
+
+		fan3pin = !(regval & (1 << 5));
+		fan4pin = !(regval & (1 << 6));
+		fan5pin = !(regval & (1 << 7));
+
+		pwm3pin = !(regval & (1 << 0));
+		pwm4pin = !(regval & (1 << 1));
+		pwm5pin = !(regval & (1 << 2));
+
+		fan3min = fan3pin;
+		fan4min = fan4pin;
+	}
+
+	superio_exit(sio_data->sioreg);
+
+	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+	data->has_fan |= fan3pin << 2;
+	data->has_fan_min |= fan3min << 2;
+
+	data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+	data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+
+	data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) | (pwm5pin << 4);
+}
+
+static int __devinit nct6775_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct nct6775_sio_data *sio_data = dev->platform_data;
+	struct nct6775_data *data;
+	struct resource *res;
+	int i, s, err = 0;
+	int src, mask, available;
+	const u16 *reg_temp, *reg_temp_over, *reg_temp_hyst, *reg_temp_config;
+	const u16 *reg_temp_alternate, *reg_temp_crit;
+	int num_reg_temp;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH,
+				 DRVNAME))
+		return -EBUSY;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(struct nct6775_data),
+			    GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->kind = sio_data->kind;
+	data->addr = res->start;
+	mutex_init(&data->lock);
+	mutex_init(&data->update_lock);
+	data->name = nct6775_device_names[data->kind];
+	platform_set_drvdata(pdev, data);
+
+	switch (data->kind) {
+	case nct6775:
+		data->in_num = 9;
+		data->pwm_num = 3;
+		data->auto_pwm_num = 6;
+		data->has_fan_div = true;
+		data->temp_fixed_num = 3;
+
+		data->ALARM_BITS = NCT6775_ALARM_BITS;
+
+		data->fan_from_reg = fan_from_reg16;
+		data->fan_from_reg_min = fan_from_reg8;
+
+		data->temp_label = nct6775_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6775_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->REG_VIN = NCT6775_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6775_REG_FAN_MIN;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[3] = NCT6775_REG_FAN_MAX_OUTPUT;
+		data->REG_PWM[4] = NCT6775_REG_FAN_STEP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6775_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6775_PWM_MODE_MASK;
+		data->REG_TEMP_MON = NCT6775_REG_TEMP_MON;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL[0] = NCT6775_REG_TEMP_SEL;
+		data->REG_TEMP_SEL[1] = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6775_REG_ALARM;
+
+		reg_temp = NCT6775_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
+		reg_temp_over = NCT6775_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6775_REG_TEMP_HYST;
+		reg_temp_config = NCT6775_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6775_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6775_REG_TEMP_CRIT;
+
+		break;
+	case nct6776:
+		data->in_num = 9;
+		data->pwm_num = 3;
+		data->auto_pwm_num = 4;
+		data->has_fan_div = false;
+		data->temp_fixed_num = 3;
+
+		data->ALARM_BITS = NCT6776_ALARM_BITS;
+
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+
+		data->temp_label = nct6776_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6776_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->REG_VIN = NCT6775_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+		data->REG_TEMP_MON = NCT6775_REG_TEMP_MON;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_TEMP_OFFSET = NCT6775_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL[0] = NCT6775_REG_TEMP_SEL;
+		data->REG_TEMP_SEL[1] = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6775_REG_ALARM;
+
+		reg_temp = NCT6775_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6775_REG_TEMP);
+		reg_temp_over = NCT6775_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6775_REG_TEMP_HYST;
+		reg_temp_config = NCT6776_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6776_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6776_REG_TEMP_CRIT;
+
+		break;
+	case nct6779:
+		data->in_num = 15;
+		data->pwm_num = 5;
+		data->auto_pwm_num = 4;
+		data->has_fan_div = false;
+		data->temp_fixed_num = 6;
+
+		data->ALARM_BITS = NCT6779_ALARM_BITS;
+
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+
+		data->temp_label = nct6779_temp_label;
+		data->temp_label_num = ARRAY_SIZE(nct6779_temp_label);
+
+		data->REG_CONFIG = NCT6775_REG_CONFIG;
+		data->REG_VBAT = NCT6775_REG_VBAT;
+		data->REG_DIODE = NCT6775_REG_DIODE;
+		data->REG_VIN = NCT6779_REG_IN;
+		data->REG_IN_MINMAX[0] = NCT6775_REG_IN_MIN;
+		data->REG_IN_MINMAX[1] = NCT6775_REG_IN_MAX;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6779_REG_FAN;
+		data->REG_FAN_MODE = NCT6775_REG_FAN_MODE;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_TIME[0] = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_TIME[1] = NCT6775_REG_FAN_STEP_UP_TIME;
+		data->REG_FAN_TIME[2] = NCT6775_REG_FAN_STEP_DOWN_TIME;
+		data->REG_PWM[0] = NCT6775_REG_PWM;
+		data->REG_PWM[1] = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_PWM[2] = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_PWM[5] = NCT6775_REG_WEIGHT_DUTY_STEP;
+		data->REG_PWM[6] = NCT6776_REG_WEIGHT_DUTY_BASE;
+		data->REG_PWM_READ = NCT6775_REG_PWM_READ;
+		data->REG_PWM_MODE = NCT6776_REG_PWM_MODE;
+		data->PWM_MODE_MASK = NCT6776_PWM_MODE_MASK;
+		data->REG_TEMP_MON = NCT6775_REG_TEMP_MON;
+		data->REG_AUTO_TEMP = NCT6775_REG_AUTO_TEMP;
+		data->REG_AUTO_PWM = NCT6775_REG_AUTO_PWM;
+		data->REG_CRITICAL_TEMP = NCT6775_REG_CRITICAL_TEMP;
+		data->REG_CRITICAL_TEMP_TOLERANCE
+		  = NCT6775_REG_CRITICAL_TEMP_TOLERANCE;
+		data->REG_TEMP_OFFSET = NCT6779_REG_TEMP_OFFSET;
+		data->REG_TEMP_SOURCE = NCT6775_REG_TEMP_SOURCE;
+		data->REG_TEMP_SEL[0] = NCT6775_REG_TEMP_SEL;
+		data->REG_TEMP_SEL[1] = NCT6775_REG_WEIGHT_TEMP_SEL;
+		data->REG_WEIGHT_TEMP[0] = NCT6775_REG_WEIGHT_TEMP_STEP;
+		data->REG_WEIGHT_TEMP[1] = NCT6775_REG_WEIGHT_TEMP_STEP_TOL;
+		data->REG_WEIGHT_TEMP[2] = NCT6775_REG_WEIGHT_TEMP_BASE;
+		data->REG_ALARM = NCT6779_REG_ALARM;
+
+		reg_temp = NCT6779_REG_TEMP;
+		num_reg_temp = ARRAY_SIZE(NCT6779_REG_TEMP);
+		reg_temp_over = NCT6779_REG_TEMP_OVER;
+		reg_temp_hyst = NCT6779_REG_TEMP_HYST;
+		reg_temp_config = NCT6779_REG_TEMP_CONFIG;
+		reg_temp_alternate = NCT6779_REG_TEMP_ALTERNATE;
+		reg_temp_crit = NCT6779_REG_TEMP_CRIT;
+
+		break;
+	default:
+		return -ENODEV;
+	}
+	data->have_in = (1 << data->in_num) - 1;
+	data->have_temp = 0;
+
+	/*
+	 * On some boards, not all available temperature sources are monitored,
+	 * even though some of the monitoring registers are unused.
+	 * Get list of unused monitoring registers, then detect if any fan
+	 * controls are configured to use unmonitored temperature sources.
+	 * If so, assign the unmonitored temperature sources to available
+	 * monitoring registers.
+	 */
+	mask = 0;
+	available = 0;
+	for (i = 0; i < num_reg_temp; i++) {
+		if (reg_temp[i] == 0)
+			continue;
+
+		src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
+		if (!src || (mask & (1 << src)))
+			available |= 1 << i;
+
+		mask |= 1 << src;
+	}
+
+	/*
+	 * Now find unmonitored temperature registers and enable monitoring
+	 * if additional monitoring registers are available.
+	 */
+	for (i = 0; i < ARRAY_SIZE(data->REG_TEMP_SEL) && available; i++) {
+		int j;
+
+		if (!data->REG_TEMP_SEL[i])
+			continue;
+		for (j = 0; j < data->pwm_num && available; j++) {
+			int index;
+
+			if (!data->REG_TEMP_SEL[i][j])
+				continue;
+			src = nct6775_read_value(data,
+						 data->REG_TEMP_SEL[i][j]);
+			src &= 0x1f;
+			if (!src || (mask & (1 << src)))
+				continue;
+			if (src >= data->temp_label_num ||
+			    !strlen(data->temp_label[src])) {
+				dev_info(dev,
+					 "Select source %d:%d reg 0x%x invalid (%d)\n",
+					 i, j, data->REG_TEMP_SEL[i][j], src);
+				continue;
+			}
+
+			index = __ffs(available);
+			nct6775_write_value(data,
+					    data->REG_TEMP_SOURCE[index],
+					    src);
+			available &= ~(1 << index);
+			mask |= 1 << src;
+		}
+	}
+
+	mask = 0;
+	s = NUM_TEMP_FIXED;	/* First dynamic temperature attribute */
+	for (i = 0; i < num_reg_temp; i++) {
+		if (reg_temp[i] == 0)
+			continue;
+
+		src = nct6775_read_value(data, data->REG_TEMP_SOURCE[i]) & 0x1f;
+		if (!src || (mask & (1 << src)))
+			continue;
+
+		if (src >= data->temp_label_num ||
+		    !strlen(data->temp_label[src])) {
+			dev_info(dev,
+				 "Invalid temperature source %d at index %d, source register 0x%x, temp register 0x%x\n",
+				 src, i, data->REG_TEMP_SOURCE[i], reg_temp[i]);
+			continue;
+		}
+
+		mask |= 1 << src;
+
+		/* Use fixed index for SYSTIN(1), CPUTIN(2), AUXTIN(3) */
+		if (src <= data->temp_fixed_num) {
+			data->have_temp |= 1 << (src - 1);
+			data->have_temp_fixed |= 1 << (src - 1);
+			data->reg_temp[0][src - 1] = reg_temp[i];
+			data->reg_temp[1][src - 1] = reg_temp_over[i];
+			data->reg_temp[2][src - 1] = reg_temp_hyst[i];
+			data->reg_temp_config[src - 1] = reg_temp_config[i];
+			data->temp_src[src - 1] = src;
+			continue;
+		}
+
+		if (s >= NUM_TEMP)
+			continue;
+
+		/* Use dynamic index for other sources */
+		data->have_temp |= 1 << s;
+		data->reg_temp[0][s] = reg_temp[i];
+		data->reg_temp[1][s] = reg_temp_over[i];
+		data->reg_temp[2][s] = reg_temp_hyst[i];
+		data->reg_temp_config[s] = reg_temp_config[i];
+		if (reg_temp_crit[src - 1])
+			data->reg_temp[3][s] = reg_temp_crit[src - 1];
+
+		data->temp_src[s] = src;
+		s++;
+	}
+
+#ifdef TESTING
+	/*
+	 * Go through the list of alternate temp registers and enable
+	 * if possible.
+	 * The temperature is already monitored if the respective bit in <mask>
+	 * is set.
+	 */
+	for (i = 0; i < data->temp_label_num - 1; i++) {
+		if (!reg_temp_alternate[i])
+			continue;
+		if (mask & (1 << (i + 1)))
+			continue;
+		if (i < data->temp_fixed_num) {
+			if (data->have_temp & (1 << i))
+				continue;
+			data->have_temp |= 1 << i;
+			data->have_temp_fixed |= 1 << i;
+			data->reg_temp[0][i] = reg_temp_alternate[i];
+			data->reg_temp[1][i] = reg_temp_over[i];
+			data->reg_temp[2][i] = reg_temp_hyst[i];
+			data->temp_src[i] = i + 1;
+			continue;
+		}
+
+		if (s >= NUM_TEMP)	/* Abort if no more space */
+			break;
+
+		data->have_temp |= 1 << s;
+		data->reg_temp[0][s] = reg_temp_alternate[i];
+		data->temp_src[s] = i + 1;
+		s++;
+	}
+#endif /* TESTING */
+
+	switch (data->kind) {
+	case nct6775:
+		break;
+	case nct6776:
+		/*
+		 * On NCT6776, AUXTIN and VIN3 pins are shared.
+		 * Only way to detect it is to check if AUXTIN is used
+		 * as a temperature source, and if that source is
+		 * enabled.
+		 *
+		 * If that is the case, disable in6, which reports VIN3.
+		 * Otherwise disable temp3.
+		 */
+		if (data->have_temp & (1 << 2)) {
+			u8 reg = nct6775_read_value(data,
+						    data->reg_temp_config[2]);
+			if (reg & 0x01)
+				data->have_temp &= ~(1 << 2);
+			else
+				data->have_in &= ~(1 << 6);
+		}
+		break;
+	case nct6779:
+		/*
+		 * Shared pins:
+		 *	VIN4 / AUXTIN0
+		 *	VIN5 / AUXTIN1
+		 *	VIN6 / AUXTIN2
+		 *	VIN7 / AUXTIN3
+		 *
+		 * There does not seem to be a clean way to detect if VINx or
+		 * AUXTINx is active, so for keep both sensor types enabled
+		 * for now.
+		 */
+		break;
+	}
+
+	/* Initialize the chip */
+	nct6775_init_device(data);
+
+	data->vrm = vid_which_vrm();
+	superio_enter(sio_data->sioreg);
+	/*
+	 * Read VID value
+	 * We can get the VID input values directly at logical device D 0xe3.
+	 */
+	superio_select(sio_data->sioreg, NCT6775_LD_VID);
+	data->vid = superio_inb(sio_data->sioreg, 0xe3);
+
+	if (fan_debounce) {
+		u8 tmp;
+
+		superio_select(sio_data->sioreg, NCT6775_LD_HWM);
+		tmp = superio_inb(sio_data->sioreg,
+				  NCT6775_REG_CR_FAN_DEBOUNCE);
+		switch (data->kind) {
+		case nct6775:
+			tmp |= 0x1e;
+			break;
+		case nct6776:
+		case nct6779:
+			tmp |= 0x3e;
+			break;
+		}
+		superio_outb(sio_data->sioreg, NCT6775_REG_CR_FAN_DEBOUNCE,
+			     tmp);
+		dev_info(&pdev->dev, "Enabled fan debounce for chip %s\n",
+			 data->name);
+	}
+
+	superio_exit(sio_data->sioreg);
+
+	err = device_create_file(dev, &dev_attr_cpu0_vid);
+	if (err)
+		return err;
+
+	nct6775_check_fan_inputs(sio_data, data);
+
+	/* Read fan clock dividers immediately */
+	nct6775_update_fan_div_common(dev, data);
+
+	/* Register sysfs hooks */
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_pwm & (1 << i)))
+			continue;
+
+		err = sysfs_create_group(&dev->kobj, &nct6775_group_pwm[i]);
+		if (err)
+			goto exit_remove;
+
+		if (data->REG_PWM[3]) {
+			err = device_create_file(dev,
+					&sda_max_output[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->REG_PWM[4]) {
+			err = device_create_file(dev,
+					&sda_step_output[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->REG_PWM[6]) {
+			err = device_create_file(dev,
+					&sda_weight_duty_base[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+	}
+	for (i = 0; i < ARRAY_SIZE(sda_auto_pwm_arrays); i++) {
+		struct sensor_device_attribute_2 *attr =
+			&sda_auto_pwm_arrays[i];
+
+		if (!(data->has_pwm & (1 << attr->nr)))
+			continue;
+		if (attr->index > data->auto_pwm_num)
+			continue;
+		err = device_create_file(dev, &attr->dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < data->in_num; i++) {
+		if (!(data->have_in & (1 << i)))
+			continue;
+		err = sysfs_create_group(&dev->kobj, &nct6775_group_in[i]);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < 5; i++) {
+		if (data->has_fan & (1 << i)) {
+			err = device_create_file(dev,
+						 &sda_fan_input[i].dev_attr);
+			if (err)
+				goto exit_remove;
+			err = device_create_file(dev,
+						 &sda_fan_alarm[i].dev_attr);
+			if (err)
+				goto exit_remove;
+			if (data->kind != nct6776 &&
+			    data->kind != nct6779) {
+				err = device_create_file(dev,
+						&sda_fan_div[i].dev_attr);
+				if (err)
+					goto exit_remove;
+			}
+			if (data->has_fan_min & (1 << i)) {
+				err = device_create_file(dev,
+						&sda_fan_min[i].dev_attr);
+				if (err)
+					goto exit_remove;
+			}
+		}
+	}
+
+	for (i = 0; i < NUM_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		err = device_create_file(dev, &sda_temp_input[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		if (data->temp_label) {
+			err = device_create_file(dev,
+						 &sda_temp_label[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp[1][i]) {
+			err = device_create_file(dev,
+						 &sda_temp_max[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp[2][i]) {
+			err = device_create_file(dev,
+					&sda_temp_max_hyst[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp[3][i]) {
+			err = device_create_file(dev,
+						 &sda_temp_crit[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (!(data->have_temp_fixed & (1 << i)))
+			continue;
+		err = device_create_file(dev, &sda_temp_type[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		err = device_create_file(dev, &sda_temp_offset[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		if (i >= NUM_TEMP_ALARM ||
+		    data->ALARM_BITS[TEMP_ALARM_BASE + i] < 0)
+			continue;
+		err = device_create_file(dev, &sda_temp_alarm[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) {
+		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0)
+			continue;
+		err = device_create_file(dev, &sda_caseopen[i].dev_attr);
+		if (err)
+			goto exit_remove;
+	}
+
+	err = device_create_file(dev, &dev_attr_name);
+	if (err)
+		goto exit_remove;
+
+	data->hwmon_dev = hwmon_device_register(dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	nct6775_device_remove_files(dev);
+	return err;
+}
+
+static int __devexit nct6775_remove(struct platform_device *pdev)
+{
+	struct nct6775_data *data = platform_get_drvdata(pdev);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	nct6775_device_remove_files(&pdev->dev);
+
+	return 0;
+}
+
+static struct platform_driver nct6775_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= nct6775_probe,
+	.remove		= __devexit_p(nct6775_remove),
+};
+
+/* nct6775_find() looks for a '627 in the Super-I/O config space */
+static int __init nct6775_find(int sioaddr, unsigned short *addr,
+			       struct nct6775_sio_data *sio_data)
+{
+	static const char __initdata sio_name_NCT6775[] = "NCT6775F";
+	static const char __initdata sio_name_NCT6776[] = "NCT6776F";
+	static const char __initdata sio_name_NCT6779[] = "NCT6779D";
+
+	u16 val;
+	const char *sio_name;
+
+	superio_enter(sioaddr);
+
+	if (force_id)
+		val = force_id;
+	else
+		val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
+		    | superio_inb(sioaddr, SIO_REG_DEVID + 1);
+	switch (val & SIO_ID_MASK) {
+	case SIO_NCT6775_ID:
+		sio_data->kind = nct6775;
+		sio_name = sio_name_NCT6775;
+		break;
+	case SIO_NCT6776_ID:
+		sio_data->kind = nct6776;
+		sio_name = sio_name_NCT6776;
+		break;
+	case SIO_NCT6779_ID:
+		sio_data->kind = nct6779;
+		sio_name = sio_name_NCT6779;
+		break;
+	default:
+		if (val != 0xffff)
+			pr_debug("unsupported chip ID: 0x%04x\n", val);
+		superio_exit(sioaddr);
+		return -ENODEV;
+	}
+
+	/* We have a known chip, find the HWM I/O address */
+	superio_select(sioaddr, NCT6775_LD_HWM);
+	val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
+	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);
+	*addr = val & IOREGION_ALIGNMENT;
+	if (*addr == 0) {
+		pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");
+		superio_exit(sioaddr);
+		return -ENODEV;
+	}
+
+	/* Activate logical device if needed */
+	val = superio_inb(sioaddr, SIO_REG_ENABLE);
+	if (!(val & 0x01)) {
+		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
+		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
+	}
+
+	superio_exit(sioaddr);
+	pr_info("Found %s chip at %#x\n", sio_name, *addr);
+	sio_data->sioreg = sioaddr;
+
+	return 0;
+}
+
+/*
+ * when Super-I/O functions move to a separate file, the Super-I/O
+ * bus will manage the lifetime of the device and this module will only keep
+ * track of the nct6775 driver. But since we platform_device_alloc(), we
+ * must keep track of the device
+ */
+static struct platform_device *pdev;
+
+static int __init sensors_nct6775_init(void)
+{
+	int err;
+	unsigned short address;
+	struct resource res;
+	struct nct6775_sio_data sio_data;
+
+	/*
+	 * initialize sio_data->kind and sio_data->sioreg.
+	 *
+	 * when Super-I/O functions move to a separate file, the Super-I/O
+	 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
+	 * nct6775 hardware monitor, and call probe()
+	 */
+	if (nct6775_find(0x2e, &address, &sio_data) &&
+	    nct6775_find(0x4e, &address, &sio_data))
+		return -ENODEV;
+
+	err = platform_driver_register(&nct6775_driver);
+	if (err)
+		goto exit;
+
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
+		err = -ENOMEM;
+		pr_err("Device allocation failed\n");
+		goto exit_unregister;
+	}
+
+	err = platform_device_add_data(pdev, &sio_data,
+				       sizeof(struct nct6775_sio_data));
+	if (err) {
+		pr_err("Platform data allocation failed\n");
+		goto exit_device_put;
+	}
+
+	memset(&res, 0, sizeof(res));
+	res.name = DRVNAME;
+	res.start = address + IOREGION_OFFSET;
+	res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
+	res.flags = IORESOURCE_IO;
+
+	err = acpi_check_resource_conflict(&res);
+	if (err)
+		goto exit_device_put;
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		pr_err("Device resource addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	/* platform_device_add calls probe() */
+	err = platform_device_add(pdev);
+	if (err) {
+		pr_err("Device addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit_unregister:
+	platform_driver_unregister(&nct6775_driver);
+exit:
+	return err;
+}
+
+static void __exit sensors_nct6775_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&nct6775_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <linux <at> roeck-us.net>");
+MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_nct6775_init);
+module_exit(sensors_nct6775_exit);
--

-- 
1.7.5.4


_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

Sven Daffner | 21 May 05:01

gelegenheit zur webverbesserung

Hallo,

Mein Name ist Sven und ich bin der Webmaster von SEO DE.

Nebenbei arbeite ich auch für meine anderen Projekt-Webseiten und dadurch
stieß ich auf lists.lm-sensors.org und ich schätze wirklich das gute Design und die Informationen.

Ich habe Seiten von sehr guter Qualität , von wo aus Sie verlinkt würden.
Wie Sie vielleicht wissen, Links von guter Qualität könnenauf jeden Fall
helfen beim Page Rank, Verkehr und bei höherer Platzierung in den wichtigsten Suchmaschinen
wie Google, Yahoo und Bing.

Sollten Sie Interesse an weiteren Details haben, dann melden Sie sich bitte zurück bei mir
und ich werde Ihnen den perfekte Vorschlag für Ihre Website machen, der bei der Verbesserung
Ihrer Website in allen Aspektenhilft.

Hoffebaldvon Ihnen zu hören und einen schönen Tag wünsche ich Ihnen

Mit freundlichen Grüßen,

Sven Daffner
SEOde.org

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Guenter Roeck | 21 May 02:59

[PATCH] sensors-detect: Add detection of NCT6779D and NCT6102D/NCT6106D

Signed-off-by: Guenter Roeck <linux <at> roeck-us.net>
---
 CHANGES                    |    1 +
 prog/detect/sensors-detect |   12 ++++++++++++
 2 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/CHANGES b/CHANGES
index 615ed65..b08d205 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,6 +6,7 @@ SVN HEAD
   sensors: Fix libiconv linkage need detection in rare corner case
   sensors-detect: Don't choke on systems without PCI
                   Avoid probing EDID addresses on graphics cards (#2386)
+		  Add detection of NCT6779D and NCT6102D/NCT6106D

 3.3.2 (2012-03-14)
   libsensors: Added support for new sysfs attributes
diff --git a/prog/detect/sensors-detect b/prog/detect/sensors-detect
index 58f7fd0..6bfd1e2 100755
--- a/prog/detect/sensors-detect
+++ b/prog/detect/sensors-detect
@@ -2034,6 +2034,18 @@ use constant FEAT_SMBUS	=> (1 << 7);
 		logdev => 0x0b,
 		features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
 	}, {
+		name => "Nuvoton NCT6779D Super IO Sensors",
+		driver => "to-be-written",	# nct6775, new driver
+		devid => 0xC562,
+		logdev => 0x0b,
+		features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
+	}, {
+		name => "Nuvoton NCT6102D/NCT6106D Super IO Sensors",
+		driver => "to-be-written",	# nct6775, new driver
+		devid => 0x1061,
+		logdev => 0x0b,
+		features => FEAT_IN | FEAT_FAN | FEAT_TEMP,
+	}, {
 		name => "Fintek F71805F/FG Super IO Sensors",
 		driver => "f71805f",
 		devid => 0x0406,
--

-- 
1.7.5.4

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors

Andrée 'Glaucous' | 20 May 19:19
Picon

Fan control for Asus P8Z77

Hi,


The (somewhat) new Asus P8Z77 boards have arrived, I'm wondering how the status for fan control is for them?
I have a Asus P8Z77-V Pro, tried both it87 and asus_atk0110, both result in that pwmconfig cannot find any controllable fans.

Currently running libsensors version 3.3.2+SVN. I'm up for testing any patches related to this chipset.
_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
Guenter Roeck | 19 May 20:48

[PATCH 1/2] hwmon: (pmbus) Add support for non-standard status register

Not all PMBus devices support the byte status register at 0x78.
Add support for non-standard status registers to work around this problem.

Signed-off-by: Guenter Roeck <linux <at> roeck-us.net>
---
 drivers/hwmon/pmbus/pmbus.h      |    1 +
 drivers/hwmon/pmbus/pmbus_core.c |   13 +++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index 3fe03dc..8073dc4 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -332,6 +332,7 @@ struct pmbus_driver_info {
 	int R[PSC_NUM_CLASSES];	/* exponent */

 	u32 func[PMBUS_PAGES];	/* Functionality, per page */
+	u8 status_register;	/* Set if not PMBUS_STATUS_BYTE */
 	/*
 	 * The following functions map manufacturing specific register values
 	 * to PMBus standard register values. Specify only if mapping is
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 29b319d..0d8d50c 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -150,6 +150,7 @@ struct pmbus_data {
 	 * so we keep them all together.
 	 */
 	u8 status[PB_NUM_STATUS_REG];
+	u8 status_register;

 	u8 currpage;
 };
@@ -318,9 +319,10 @@ EXPORT_SYMBOL_GPL(pmbus_clear_faults);

 static int pmbus_check_status_cml(struct i2c_client *client)
 {
+	struct pmbus_data *data = i2c_get_clientdata(client);
 	int status, status2;

-	status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE);
+	status = _pmbus_read_byte_data(client, -1, data->status_register);
 	if (status < 0 || (status & PB_STATUS_CML)) {
 		status2 = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_CML);
 		if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
@@ -376,7 +378,7 @@ static struct pmbus_data *pmbus_update_device(struct device *dev)
 		for (i = 0; i < info->pages; i++)
 			data->status[PB_STATUS_BASE + i]
 			    = _pmbus_read_byte_data(client, i,
-						    PMBUS_STATUS_BYTE);
+						    data->status_register);
 		for (i = 0; i < info->pages; i++) {
 			if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT))
 				continue;
@@ -1069,7 +1071,8 @@ static void pmbus_add_sensor_attrs_one(struct i2c_client *client,
 		 * the generic status register for this page is accessible.
 		 */
 		if (!have_alarm && attr->gbit &&
-		    pmbus_check_byte_register(client, page, PMBUS_STATUS_BYTE))
+		    pmbus_check_byte_register(client, page,
+					      data->status_register))
 			pmbus_add_boolean_reg(data, name, "alarm", index,
 					      PB_STATUS_BASE + page,
 					      attr->gbit);
@@ -1704,8 +1707,10 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
 	i2c_set_clientdata(client, data);
 	mutex_init(&data->update_lock);

+	data->status_register = info->status_register ? : PMBUS_STATUS_BYTE;
+
 	/* Bail out if PMBus status register does not exist. */
-	if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) {
+	if (i2c_smbus_read_byte_data(client, data->status_register) < 0) {
 		dev_err(&client->dev, "PMBus status register not found\n");
 		return -ENODEV;
 	}
--

-- 
1.7.5.4

_______________________________________________
lm-sensors mailing list
lm-sensors <at> lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors


Gmane