From 871480933a1c28f8a9fed4c4d34d06c439a7a422 Mon Sep 17 00:00:00 2001 From: Srikant Patnaik Date: Sun, 11 Jan 2015 12:28:04 +0530 Subject: Moved, renamed, and deleted files The original directory structure was scattered and unorganized. Changes are basically to make it look like kernel structure. --- ANDROID_3.4.5/drivers/hwmon/Kconfig | 1407 ----------- ANDROID_3.4.5/drivers/hwmon/Makefile | 133 - ANDROID_3.4.5/drivers/hwmon/abituguru.c | 1646 ------------- ANDROID_3.4.5/drivers/hwmon/abituguru3.c | 1322 ---------- ANDROID_3.4.5/drivers/hwmon/acpi_power_meter.c | 1026 -------- ANDROID_3.4.5/drivers/hwmon/ad7314.c | 174 -- ANDROID_3.4.5/drivers/hwmon/ad7414.c | 266 -- ANDROID_3.4.5/drivers/hwmon/ad7418.c | 303 --- ANDROID_3.4.5/drivers/hwmon/adcxx.c | 255 -- ANDROID_3.4.5/drivers/hwmon/adm1021.c | 486 ---- ANDROID_3.4.5/drivers/hwmon/adm1025.c | 625 ----- ANDROID_3.4.5/drivers/hwmon/adm1026.c | 1904 --------------- ANDROID_3.4.5/drivers/hwmon/adm1029.c | 460 ---- ANDROID_3.4.5/drivers/hwmon/adm1031.c | 1140 --------- ANDROID_3.4.5/drivers/hwmon/adm9240.c | 831 ------- ANDROID_3.4.5/drivers/hwmon/ads1015.c | 311 --- ANDROID_3.4.5/drivers/hwmon/ads7828.c | 274 --- ANDROID_3.4.5/drivers/hwmon/ads7871.c | 249 -- ANDROID_3.4.5/drivers/hwmon/adt7411.c | 356 --- ANDROID_3.4.5/drivers/hwmon/adt7462.c | 1981 --------------- ANDROID_3.4.5/drivers/hwmon/adt7470.c | 1324 ---------- ANDROID_3.4.5/drivers/hwmon/adt7475.c | 1633 ------------- ANDROID_3.4.5/drivers/hwmon/amc6821.c | 1105 --------- ANDROID_3.4.5/drivers/hwmon/applesmc.c | 1338 ---------- ANDROID_3.4.5/drivers/hwmon/asb100.c | 1025 -------- ANDROID_3.4.5/drivers/hwmon/asc7621.c | 1249 ---------- ANDROID_3.4.5/drivers/hwmon/asus_atk0110.c | 1463 ----------- ANDROID_3.4.5/drivers/hwmon/atxp1.c | 398 --- ANDROID_3.4.5/drivers/hwmon/coretemp.c | 830 ------- ANDROID_3.4.5/drivers/hwmon/dme1737.c | 2815 ---------------------- ANDROID_3.4.5/drivers/hwmon/ds1621.c | 321 --- ANDROID_3.4.5/drivers/hwmon/ds620.c | 304 --- ANDROID_3.4.5/drivers/hwmon/emc1403.c | 377 --- ANDROID_3.4.5/drivers/hwmon/emc2103.c | 733 ------ ANDROID_3.4.5/drivers/hwmon/emc6w201.c | 559 ----- ANDROID_3.4.5/drivers/hwmon/exynos4_tmu.c | 514 ---- ANDROID_3.4.5/drivers/hwmon/f71805f.c | 1669 ------------- ANDROID_3.4.5/drivers/hwmon/f71882fg.c | 2708 --------------------- ANDROID_3.4.5/drivers/hwmon/f75375s.c | 926 ------- ANDROID_3.4.5/drivers/hwmon/fam15h_power.c | 271 --- ANDROID_3.4.5/drivers/hwmon/fschmd.c | 1388 ----------- ANDROID_3.4.5/drivers/hwmon/g760a.c | 258 -- ANDROID_3.4.5/drivers/hwmon/gl518sm.c | 723 ------ ANDROID_3.4.5/drivers/hwmon/gl520sm.c | 981 -------- ANDROID_3.4.5/drivers/hwmon/gpio-fan.c | 547 ----- ANDROID_3.4.5/drivers/hwmon/hwmon-vid.c | 307 --- ANDROID_3.4.5/drivers/hwmon/hwmon.c | 127 - ANDROID_3.4.5/drivers/hwmon/i5k_amb.c | 621 ----- ANDROID_3.4.5/drivers/hwmon/ibmaem.c | 1117 --------- ANDROID_3.4.5/drivers/hwmon/ibmpex.c | 618 ----- ANDROID_3.4.5/drivers/hwmon/it87.c | 2377 ------------------ ANDROID_3.4.5/drivers/hwmon/jc42.c | 595 ----- ANDROID_3.4.5/drivers/hwmon/jz4740-hwmon.c | 220 -- ANDROID_3.4.5/drivers/hwmon/k10temp.c | 239 -- ANDROID_3.4.5/drivers/hwmon/k8temp.c | 357 --- ANDROID_3.4.5/drivers/hwmon/lineage-pem.c | 572 ----- ANDROID_3.4.5/drivers/hwmon/lm63.c | 1214 ---------- ANDROID_3.4.5/drivers/hwmon/lm70.c | 223 -- ANDROID_3.4.5/drivers/hwmon/lm73.c | 201 -- ANDROID_3.4.5/drivers/hwmon/lm75.c | 445 ---- ANDROID_3.4.5/drivers/hwmon/lm75.h | 49 - ANDROID_3.4.5/drivers/hwmon/lm77.c | 458 ---- ANDROID_3.4.5/drivers/hwmon/lm78.c | 1126 --------- ANDROID_3.4.5/drivers/hwmon/lm80.c | 737 ------ ANDROID_3.4.5/drivers/hwmon/lm83.c | 437 ---- ANDROID_3.4.5/drivers/hwmon/lm85.c | 1720 ------------- ANDROID_3.4.5/drivers/hwmon/lm87.c | 1021 -------- ANDROID_3.4.5/drivers/hwmon/lm90.c | 1553 ------------ ANDROID_3.4.5/drivers/hwmon/lm92.c | 449 ---- ANDROID_3.4.5/drivers/hwmon/lm93.c | 2814 --------------------- ANDROID_3.4.5/drivers/hwmon/lm95241.c | 462 ---- ANDROID_3.4.5/drivers/hwmon/lm95245.c | 532 ---- ANDROID_3.4.5/drivers/hwmon/ltc4151.c | 246 -- ANDROID_3.4.5/drivers/hwmon/ltc4215.c | 321 --- ANDROID_3.4.5/drivers/hwmon/ltc4245.c | 588 ----- ANDROID_3.4.5/drivers/hwmon/ltc4261.c | 297 --- ANDROID_3.4.5/drivers/hwmon/max1111.c | 236 -- ANDROID_3.4.5/drivers/hwmon/max16065.c | 697 ------ ANDROID_3.4.5/drivers/hwmon/max1619.c | 368 --- ANDROID_3.4.5/drivers/hwmon/max1668.c | 491 ---- ANDROID_3.4.5/drivers/hwmon/max6639.c | 651 ----- ANDROID_3.4.5/drivers/hwmon/max6642.c | 359 --- ANDROID_3.4.5/drivers/hwmon/max6650.c | 738 ------ ANDROID_3.4.5/drivers/hwmon/mc13783-adc.c | 299 --- ANDROID_3.4.5/drivers/hwmon/mcp3021.c | 171 -- ANDROID_3.4.5/drivers/hwmon/ntc_thermistor.c | 440 ---- ANDROID_3.4.5/drivers/hwmon/pc87360.c | 1832 -------------- ANDROID_3.4.5/drivers/hwmon/pc87427.c | 1383 ----------- ANDROID_3.4.5/drivers/hwmon/pcf8591.c | 342 --- ANDROID_3.4.5/drivers/hwmon/pmbus/Kconfig | 124 - ANDROID_3.4.5/drivers/hwmon/pmbus/Makefile | 15 - ANDROID_3.4.5/drivers/hwmon/pmbus/adm1275.c | 397 --- ANDROID_3.4.5/drivers/hwmon/pmbus/lm25066.c | 321 --- ANDROID_3.4.5/drivers/hwmon/pmbus/ltc2978.c | 378 --- ANDROID_3.4.5/drivers/hwmon/pmbus/max16064.c | 127 - ANDROID_3.4.5/drivers/hwmon/pmbus/max34440.c | 364 --- ANDROID_3.4.5/drivers/hwmon/pmbus/max8688.c | 204 -- ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.c | 217 -- ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.h | 376 --- ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus_core.c | 1811 -------------- ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9000.c | 246 -- ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9200.c | 180 -- ANDROID_3.4.5/drivers/hwmon/pmbus/zl6100.c | 259 -- ANDROID_3.4.5/drivers/hwmon/s3c-hwmon.c | 401 --- ANDROID_3.4.5/drivers/hwmon/sch5627.c | 606 ----- ANDROID_3.4.5/drivers/hwmon/sch5636.c | 537 ----- ANDROID_3.4.5/drivers/hwmon/sch56xx-common.c | 855 ------- ANDROID_3.4.5/drivers/hwmon/sch56xx-common.h | 32 - ANDROID_3.4.5/drivers/hwmon/sht15.c | 1118 --------- ANDROID_3.4.5/drivers/hwmon/sht21.c | 268 -- ANDROID_3.4.5/drivers/hwmon/sis5595.c | 942 -------- ANDROID_3.4.5/drivers/hwmon/smm665.c | 720 ------ ANDROID_3.4.5/drivers/hwmon/smsc47b397.c | 422 ---- ANDROID_3.4.5/drivers/hwmon/smsc47m1.c | 975 -------- ANDROID_3.4.5/drivers/hwmon/smsc47m192.c | 682 ------ ANDROID_3.4.5/drivers/hwmon/thmc50.c | 488 ---- ANDROID_3.4.5/drivers/hwmon/tmp102.c | 299 --- ANDROID_3.4.5/drivers/hwmon/tmp401.c | 669 ----- ANDROID_3.4.5/drivers/hwmon/tmp421.c | 332 --- ANDROID_3.4.5/drivers/hwmon/twl4030-madc-hwmon.c | 144 -- ANDROID_3.4.5/drivers/hwmon/ultra45_env.c | 326 --- ANDROID_3.4.5/drivers/hwmon/via-cputemp.c | 386 --- ANDROID_3.4.5/drivers/hwmon/via686a.c | 976 -------- ANDROID_3.4.5/drivers/hwmon/vt1211.c | 1380 ----------- ANDROID_3.4.5/drivers/hwmon/vt8231.c | 1082 --------- ANDROID_3.4.5/drivers/hwmon/w83627ehf.c | 2800 --------------------- ANDROID_3.4.5/drivers/hwmon/w83627hf.c | 1948 --------------- ANDROID_3.4.5/drivers/hwmon/w83781d.c | 2118 ---------------- ANDROID_3.4.5/drivers/hwmon/w83791d.c | 1706 ------------- ANDROID_3.4.5/drivers/hwmon/w83792d.c | 1729 ------------- ANDROID_3.4.5/drivers/hwmon/w83793.c | 2199 ----------------- ANDROID_3.4.5/drivers/hwmon/w83795.c | 2291 ------------------ ANDROID_3.4.5/drivers/hwmon/w83l785ts.c | 312 --- ANDROID_3.4.5/drivers/hwmon/w83l786ng.c | 817 ------- ANDROID_3.4.5/drivers/hwmon/wm831x-hwmon.c | 219 -- ANDROID_3.4.5/drivers/hwmon/wm8350-hwmon.c | 141 -- 136 files changed, 105597 deletions(-) delete mode 100644 ANDROID_3.4.5/drivers/hwmon/Kconfig delete mode 100644 ANDROID_3.4.5/drivers/hwmon/Makefile delete mode 100644 ANDROID_3.4.5/drivers/hwmon/abituguru.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/abituguru3.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/acpi_power_meter.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ad7314.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ad7414.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ad7418.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adcxx.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adm1021.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adm1025.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adm1026.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adm1029.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adm1031.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adm9240.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ads1015.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ads7828.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ads7871.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adt7411.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adt7462.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adt7470.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/adt7475.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/amc6821.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/applesmc.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/asb100.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/asc7621.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/asus_atk0110.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/atxp1.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/coretemp.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/dme1737.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ds1621.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ds620.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/emc1403.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/emc2103.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/emc6w201.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/exynos4_tmu.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/f71805f.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/f71882fg.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/f75375s.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/fam15h_power.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/fschmd.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/g760a.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/gl518sm.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/gl520sm.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/gpio-fan.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/hwmon-vid.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/hwmon.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/i5k_amb.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ibmaem.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ibmpex.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/it87.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/jc42.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/jz4740-hwmon.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/k10temp.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/k8temp.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lineage-pem.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm63.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm70.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm73.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm75.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm75.h delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm77.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm78.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm80.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm83.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm85.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm87.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm90.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm92.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm93.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm95241.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/lm95245.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ltc4151.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ltc4215.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ltc4245.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ltc4261.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max1111.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max16065.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max1619.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max1668.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max6639.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max6642.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/max6650.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/mc13783-adc.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/mcp3021.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ntc_thermistor.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pc87360.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pc87427.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pcf8591.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/Kconfig delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/Makefile delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/adm1275.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/lm25066.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/ltc2978.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/max16064.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/max34440.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/max8688.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.h delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus_core.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9000.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9200.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/pmbus/zl6100.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/s3c-hwmon.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sch5627.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sch5636.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sch56xx-common.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sch56xx-common.h delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sht15.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sht21.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/sis5595.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/smm665.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/smsc47b397.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/smsc47m1.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/smsc47m192.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/thmc50.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/tmp102.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/tmp401.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/tmp421.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/twl4030-madc-hwmon.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/ultra45_env.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/via-cputemp.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/via686a.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/vt1211.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/vt8231.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83627ehf.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83627hf.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83781d.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83791d.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83792d.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83793.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83795.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83l785ts.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/w83l786ng.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/wm831x-hwmon.c delete mode 100644 ANDROID_3.4.5/drivers/hwmon/wm8350-hwmon.c (limited to 'ANDROID_3.4.5/drivers/hwmon') diff --git a/ANDROID_3.4.5/drivers/hwmon/Kconfig b/ANDROID_3.4.5/drivers/hwmon/Kconfig deleted file mode 100644 index 8deedc1b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/Kconfig +++ /dev/null @@ -1,1407 +0,0 @@ -# -# Hardware monitoring chip drivers configuration -# - -menuconfig HWMON - tristate "Hardware Monitoring support" - depends on HAS_IOMEM - default y - help - Hardware monitoring devices let you monitor the hardware health - of a system. Most modern motherboards include such a device. It - can include temperature sensors, voltage sensors, fan speed - sensors and various additional features such as the ability to - control the speed of the fans. If you want this support you - should say Y here and also to the specific driver(s) for your - sensors chip(s) below. - - To find out which specific driver(s) you need, use the - sensors-detect script from the lm_sensors package. Read - for details. - - This support can also be built as a module. If so, the module - will be called hwmon. - -if HWMON - -config HWMON_VID - tristate - default n - -config HWMON_DEBUG_CHIP - bool "Hardware Monitoring Chip debugging messages" - default n - help - Say Y here if you want the I2C chip drivers to produce a bunch of - debug messages to the system log. Select this if you are having - a problem with I2C support and want to see more of what is going - on. - -comment "Native drivers" - -config SENSORS_ABITUGURU - tristate "Abit uGuru (rev 1 & 2)" - depends on X86 && DMI && EXPERIMENTAL - help - If you say yes here you get support for the sensor part of the first - and second revision of the Abit uGuru chip. The voltage and frequency - control parts of the Abit uGuru are not supported. The Abit uGuru - chip can be found on Abit uGuru featuring motherboards (most modern - Abit motherboards from before end 2005). For more info and a list - of which motherboards have which revision see - Documentation/hwmon/abituguru - - This driver can also be built as a module. If so, the module - will be called abituguru. - -config SENSORS_ABITUGURU3 - tristate "Abit uGuru (rev 3)" - depends on X86 && DMI && EXPERIMENTAL - help - If you say yes here you get support for the sensor part of the - third revision of the Abit uGuru chip. Only reading the sensors - and their settings is supported. The third revision of the Abit - uGuru chip can be found on recent Abit motherboards (since end - 2005). For more info and a list of which motherboards have which - revision see Documentation/hwmon/abituguru3 - - This driver can also be built as a module. If so, the module - will be called abituguru3. - -config SENSORS_AD7314 - tristate "Analog Devices AD7314 and compatibles" - depends on SPI && EXPERIMENTAL - help - If you say yes here you get support for the Analog Devices - AD7314, ADT7301 and ADT7302 temperature sensors. - - This driver can also be built as a module. If so, the module - will be called ad7314. - -config SENSORS_AD7414 - tristate "Analog Devices AD7414" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Analog Devices - AD7414 temperature monitoring chip. - - This driver can also be built as a module. If so, the module - will be called ad7414. - -config SENSORS_AD7418 - tristate "Analog Devices AD7416, AD7417 and AD7418" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Analog Devices - AD7416, AD7417 and AD7418 temperature monitoring chips. - - This driver can also be built as a module. If so, the module - will be called ad7418. - -config SENSORS_ADCXX - tristate "National Semiconductor ADCxxxSxxx" - depends on SPI_MASTER && EXPERIMENTAL - help - If you say yes here you get support for the National Semiconductor - ADCS chip family, where - * bb is the resolution in number of bits (8, 10, 12) - * c is the number of channels (1, 2, 4, 8) - * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500 - kSPS and 101 for 1 MSPS) - - Examples : ADC081S101, ADC124S501, ... - - This driver can also be built as a module. If so, the module - will be called adcxx. - -config SENSORS_ADM1021 - tristate "Analog Devices ADM1021 and compatibles" - depends on I2C - help - If you say yes here you get support for Analog Devices ADM1021 - and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A, - Genesys Logic GL523SM, National Semiconductor LM84 and TI THMC10. - - This driver can also be built as a module. If so, the module - will be called adm1021. - -config SENSORS_ADM1025 - tristate "Analog Devices ADM1025 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for Analog Devices ADM1025 - and Philips NE1619 sensor chips. - - This driver can also be built as a module. If so, the module - will be called adm1025. - -config SENSORS_ADM1026 - tristate "Analog Devices ADM1026 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for Analog Devices ADM1026 - sensor chip. - - This driver can also be built as a module. If so, the module - will be called adm1026. - -config SENSORS_ADM1029 - tristate "Analog Devices ADM1029" - depends on I2C - help - If you say yes here you get support for Analog Devices ADM1029 - sensor chip. - Very rare chip, please let us know you use it. - - This driver can also be built as a module. If so, the module - will be called adm1029. - -config SENSORS_ADM1031 - tristate "Analog Devices ADM1031 and compatibles" - depends on I2C - help - If you say yes here you get support for Analog Devices ADM1031 - and ADM1030 sensor chips. - - This driver can also be built as a module. If so, the module - will be called adm1031. - -config SENSORS_ADM9240 - tristate "Analog Devices ADM9240 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for Analog Devices ADM9240, - Dallas DS1780, National Semiconductor LM81 sensor chips. - - This driver can also be built as a module. If so, the module - will be called adm9240. - -config SENSORS_ADT7411 - tristate "Analog Devices ADT7411" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Analog Devices - ADT7411 voltage and temperature monitoring chip. - - This driver can also be built as a module. If so, the module - will be called adt7411. - -config SENSORS_ADT7462 - tristate "Analog Devices ADT7462" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Analog Devices - ADT7462 temperature monitoring chips. - - This driver can also be built as a module. If so, the module - will be called adt7462. - -config SENSORS_ADT7470 - tristate "Analog Devices ADT7470" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Analog Devices - ADT7470 temperature monitoring chips. - - This driver can also be built as a module. If so, the module - will be called adt7470. - -config SENSORS_ADT7475 - tristate "Analog Devices ADT7473, ADT7475, ADT7476 and ADT7490" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for the Analog Devices - ADT7473, ADT7475, ADT7476 and ADT7490 hardware monitoring - chips. - - This driver can also be build as a module. If so, the module - will be called adt7475. - -config SENSORS_ASC7621 - tristate "Andigilog aSC7621" - depends on I2C - help - If you say yes here you get support for the aSC7621 - family of SMBus sensors chip found on most Intel X38, X48, X58, - 945, 965 and 975 desktop boards. Currently supported chips: - aSC7621 - aSC7621a - - This driver can also be built as a module. If so, the module - will be called asc7621. - -config SENSORS_K8TEMP - tristate "AMD Athlon64/FX or Opteron temperature sensor" - depends on X86 && PCI && EXPERIMENTAL - help - If you say yes here you get support for the temperature - sensor(s) inside your CPU. Supported is whole AMD K8 - microarchitecture. Please note that you will need at least - lm-sensors 2.10.1 for proper userspace support. - - This driver can also be built as a module. If so, the module - will be called k8temp. - -config SENSORS_K10TEMP - tristate "AMD Family 10h+ temperature sensor" - depends on X86 && PCI - help - If you say yes here you get support for the temperature - sensor(s) inside your CPU. Supported are later revisions of - the AMD Family 10h and all revisions of the AMD Family 11h, - 12h (Llano), 14h (Brazos) and 15h (Bulldozer/Trinity) - microarchitectures. - - This driver can also be built as a module. If so, the module - will be called k10temp. - -config SENSORS_FAM15H_POWER - tristate "AMD Family 15h processor power" - depends on X86 && PCI - help - If you say yes here you get support for processor power - information of your AMD family 15h CPU. - - This driver can also be built as a module. If so, the module - will be called fam15h_power. - -config SENSORS_ASB100 - tristate "Asus ASB100 Bach" - depends on X86 && I2C && EXPERIMENTAL - select HWMON_VID - help - If you say yes here you get support for the ASB100 Bach sensor - chip found on some Asus mainboards. - - This driver can also be built as a module. If so, the module - will be called asb100. - -config SENSORS_ATXP1 - tristate "Attansic ATXP1 VID controller" - depends on I2C && EXPERIMENTAL - select HWMON_VID - help - If you say yes here you get support for the Attansic ATXP1 VID - controller. - - If your board have such a chip, you are able to control your CPU - core and other voltages. - - This driver can also be built as a module. If so, the module - will be called atxp1. - -config SENSORS_DS620 - tristate "Dallas Semiconductor DS620" - depends on I2C - help - If you say yes here you get support for Dallas Semiconductor - DS620 sensor chip. - - This driver can also be built as a module. If so, the module - will be called ds620. - -config SENSORS_DS1621 - tristate "Dallas Semiconductor DS1621 and DS1625" - depends on I2C - help - If you say yes here you get support for Dallas Semiconductor - DS1621 and DS1625 sensor chips. - - This driver can also be built as a module. If so, the module - will be called ds1621. - -config SENSORS_EXYNOS4_TMU - tristate "Temperature sensor on Samsung EXYNOS4" - depends on ARCH_EXYNOS4 - help - If you say yes here you get support for TMU (Thermal Managment - Unit) on SAMSUNG EXYNOS4 series of SoC. - - This driver can also be built as a module. If so, the module - will be called exynos4-tmu. - -config SENSORS_I5K_AMB - tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" - depends on PCI && EXPERIMENTAL - help - If you say yes here you get support for FB-DIMM AMB temperature - monitoring chips on systems with the Intel 5000 series chipset. - - This driver can also be built as a module. If so, the module - will be called i5k_amb. - -config SENSORS_F71805F - tristate "Fintek F71805F/FG, F71806F/FG and F71872F/FG" - depends on !PPC - help - If you say yes here you get support for hardware monitoring - features of the Fintek F71805F/FG, F71806F/FG and F71872F/FG - Super-I/O chips. - - This driver can also be built as a module. If so, the module - will be called f71805f. - -config SENSORS_F71882FG - tristate "Fintek F71882FG and compatibles" - depends on !PPC - help - If you say yes here you get support for hardware monitoring - features of many Fintek Super-I/O (LPC) chips. The currently - supported chips are: - F71808E/A - F71858FG - F71862FG - F71863FG - F71869F/E/A - F71882FG - F71883FG - F71889FG/ED/A - F8000 - F81801U - F81865F - - This driver can also be built as a module. If so, the module - will be called f71882fg. - -config SENSORS_F75375S - tristate "Fintek F75375S/SP, F75373 and F75387" - depends on I2C - help - If you say yes here you get support for hardware monitoring - features of the Fintek F75375S/SP, F75373 and F75387 - - This driver can also be built as a module. If so, the module - will be called f75375s. - -config SENSORS_FSCHMD - tristate "Fujitsu Siemens Computers sensor chips" - depends on X86 && I2C - help - If you say yes here you get support for the following Fujitsu - Siemens Computers (FSC) sensor chips: Poseidon, Scylla, Hermes, - Heimdall, Heracles, Hades and Syleus including support for the - integrated watchdog. - - This is a merged driver for FSC sensor chips replacing the fscpos, - fscscy and fscher drivers and adding support for several other FSC - sensor chips. - - This driver can also be built as a module. If so, the module - will be called fschmd. - -config SENSORS_G760A - tristate "GMT G760A" - depends on I2C - help - If you say yes here you get support for Global Mixed-mode - Technology Inc G760A fan speed PWM controller chips. - - This driver can also be built as a module. If so, the module - will be called g760a. - -config SENSORS_GL518SM - tristate "Genesys Logic GL518SM" - depends on I2C - help - If you say yes here you get support for Genesys Logic GL518SM - sensor chips. - - This driver can also be built as a module. If so, the module - will be called gl518sm. - -config SENSORS_GL520SM - tristate "Genesys Logic GL520SM" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for Genesys Logic GL520SM - sensor chips. - - This driver can also be built as a module. If so, the module - will be called gl520sm. - -config SENSORS_GPIO_FAN - tristate "GPIO fan" - depends on GPIOLIB - help - If you say yes here you get support for fans connected to GPIO lines. - - This driver can also be built as a module. If so, the module - will be called gpio-fan. - -config SENSORS_CORETEMP - tristate "Intel Core/Core2/Atom temperature sensor" - depends on X86 && PCI && EXPERIMENTAL - help - If you say yes here you get support for the temperature - sensor inside your CPU. Most of the family 6 CPUs - are supported. Check Documentation/hwmon/coretemp for details. - -config SENSORS_IBMAEM - tristate "IBM Active Energy Manager temperature/power sensors and control" - select IPMI_SI - depends on IPMI_HANDLER - help - If you say yes here you get support for the temperature and - power sensors and capping hardware in various IBM System X - servers that support Active Energy Manager. This includes - the x3350, x3550, x3650, x3655, x3755, x3850 M2, x3950 M2, - and certain HC10/HS2x/LS2x/QS2x blades. - - This driver can also be built as a module. If so, the module - will be called ibmaem. - -config SENSORS_IBMPEX - tristate "IBM PowerExecutive temperature/power sensors" - select IPMI_SI - depends on IPMI_HANDLER - help - If you say yes here you get support for the temperature and - power sensors in various IBM System X servers that support - PowerExecutive. So far this includes the x3350, x3550, x3650, - x3655, and x3755; the x3800, x3850, and x3950 models that have - PCI Express; and some of the HS2x, LS2x, and QS2x blades. - - This driver can also be built as a module. If so, the module - will be called ibmpex. - -config SENSORS_IT87 - tristate "ITE IT87xx and compatibles" - depends on !PPC - select HWMON_VID - help - If you say yes here you get support for ITE IT8705F, IT8712F, - IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E - sensor chips, and the SiS960 clone. - - This driver can also be built as a module. If so, the module - will be called it87. - -config SENSORS_JZ4740 - tristate "Ingenic JZ4740 SoC ADC driver" - depends on MACH_JZ4740 && MFD_JZ4740_ADC - help - If you say yes here you get support for reading adc values from the ADCIN - pin on Ingenic JZ4740 SoC based boards. - - This driver can also be build as a module. If so, the module will be - called jz4740-hwmon. - -config SENSORS_JC42 - tristate "JEDEC JC42.4 compliant memory module temperature sensors" - depends on I2C - help - If you say yes here, you get support for JEDEC JC42.4 compliant - temperature sensors, which are used on many DDR3 memory modules for - mobile devices and servers. Support will include, but not be limited - to, ADT7408, AT30TS00, CAT34TS02, CAT6095, MAX6604, MCP9804, MCP9805, - MCP98242, MCP98243, MCP9843, SE97, SE98, STTS424(E), STTS2002, - STTS3000, TSE2002B3, TSE2002GB2, TS3000B3, and TS3000GB2. - - This driver can also be built as a module. If so, the module - will be called jc42. - -config SENSORS_LINEAGE - tristate "Lineage Compact Power Line Power Entry Module" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Lineage Compact Power Line - series of DC/DC and AC/DC converters such as CP1800, CP2000AC, - CP2000DC, CP2725, and others. - - This driver can also be built as a module. If so, the module - will be called lineage-pem. - -config SENSORS_LM63 - tristate "National Semiconductor LM63 and compatibles" - depends on I2C - help - If you say yes here you get support for the National - Semiconductor LM63, LM64, and LM96163 remote diode digital temperature - sensors with integrated fan control. Such chips are found - on the Tyan S4882 (Thunder K8QS Pro) motherboard, among - others. - - This driver can also be built as a module. If so, the module - will be called lm63. - -config SENSORS_LM70 - tristate "National Semiconductor LM70 / Texas Instruments TMP121" - depends on SPI_MASTER - help - If you say yes here you get support for the National Semiconductor - LM70 and Texas Instruments TMP121/TMP123 digital temperature - sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm70. - -config SENSORS_LM73 - tristate "National Semiconductor LM73" - depends on I2C - help - If you say yes here you get support for National Semiconductor LM73 - sensor chips. - This driver can also be built as a module. If so, the module - will be called lm73. - -config SENSORS_LM75 - tristate "National Semiconductor LM75 and compatibles" - depends on I2C - help - If you say yes here you get support for one common type of - temperature sensor chip, with models including: - - - Analog Devices ADT75 - - Dallas Semiconductor DS75 and DS1775 - - Maxim MAX6625 and MAX6626 - - Microchip MCP980x - - National Semiconductor LM75, LM75A - - NXP's LM75A - - ST Microelectronics STDS75 - - TelCom (now Microchip) TCN75 - - Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, - TMP275 - - This driver supports driver model based binding through board - specific I2C device tables. - - It also supports the "legacy" style of driver binding. To use - that with some chips which don't replicate LM75 quirks exactly, - you may need the "force" module parameter. - - This driver can also be built as a module. If so, the module - will be called lm75. - -config SENSORS_LM77 - tristate "National Semiconductor LM77" - depends on I2C - help - If you say yes here you get support for National Semiconductor LM77 - sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm77. - -config SENSORS_LM78 - tristate "National Semiconductor LM78 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for National Semiconductor LM78, - LM78-J and LM79. - - This driver can also be built as a module. If so, the module - will be called lm78. - -config SENSORS_LM80 - tristate "National Semiconductor LM80 and LM96080" - depends on I2C - help - If you say yes here you get support for National Semiconductor - LM80 and LM96080 sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm80. - -config SENSORS_LM83 - tristate "National Semiconductor LM83 and compatibles" - depends on I2C - help - If you say yes here you get support for National Semiconductor - LM82 and LM83 sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm83. - -config SENSORS_LM85 - tristate "National Semiconductor LM85 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for National Semiconductor LM85 - sensor chips and clones: ADM1027, ADT7463, ADT7468, EMC6D100, - EMC6D101, EMC6D102, and EMC6D103. - - This driver can also be built as a module. If so, the module - will be called lm85. - -config SENSORS_LM87 - tristate "National Semiconductor LM87 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for National Semiconductor LM87 - and Analog Devices ADM1024 sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm87. - -config SENSORS_LM90 - tristate "National Semiconductor LM90 and compatibles" - depends on I2C - help - If you say yes here you get support for National Semiconductor LM90, - LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A, - Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659, - MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008, - Winbond/Nuvoton W83L771W/G/AWG/ASG, Philips SA56004, and GMT G781 - sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm90. - -config SENSORS_LM92 - tristate "National Semiconductor LM92 and compatibles" - depends on I2C - help - If you say yes here you get support for National Semiconductor LM92 - and Maxim MAX6635 sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm92. - -config SENSORS_LM93 - tristate "National Semiconductor LM93 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for National Semiconductor LM93, - LM94, and compatible sensor chips. - - This driver can also be built as a module. If so, the module - will be called lm93. - -config SENSORS_LTC4151 - tristate "Linear Technology LTC4151" - depends on I2C - default n - help - If you say yes here you get support for Linear Technology LTC4151 - High Voltage I2C Current and Voltage Monitor interface. - - This driver can also be built as a module. If so, the module will - be called ltc4151. - -config SENSORS_LTC4215 - tristate "Linear Technology LTC4215" - depends on I2C && EXPERIMENTAL - default n - help - If you say yes here you get support for Linear Technology LTC4215 - Hot Swap Controller I2C interface. - - This driver can also be built as a module. If so, the module will - be called ltc4215. - -config SENSORS_LTC4245 - tristate "Linear Technology LTC4245" - depends on I2C && EXPERIMENTAL - default n - help - If you say yes here you get support for Linear Technology LTC4245 - Multiple Supply Hot Swap Controller I2C interface. - - This driver can also be built as a module. If so, the module will - be called ltc4245. - -config SENSORS_LTC4261 - tristate "Linear Technology LTC4261" - depends on I2C && EXPERIMENTAL - default n - help - If you say yes here you get support for Linear Technology LTC4261 - Negative Voltage Hot Swap Controller I2C interface. - - This driver can also be built as a module. If so, the module will - be called ltc4261. - -config SENSORS_LM95241 - tristate "National Semiconductor LM95241 and compatibles" - depends on I2C - help - If you say yes here you get support for LM95231 and LM95241 sensor - chips. - - This driver can also be built as a module. If so, the module - will be called lm95241. - -config SENSORS_LM95245 - tristate "National Semiconductor LM95245 sensor chip" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for LM95245 sensor chip. - - This driver can also be built as a module. If so, the module - will be called lm95245. - -config SENSORS_MAX1111 - tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" - depends on SPI_MASTER - help - Say y here to support Maxim's MAX1111 ADC chips. - - This driver can also be built as a module. If so, the module - will be called max1111. - -config SENSORS_MAX16065 - tristate "Maxim MAX16065 System Manager and compatibles" - depends on I2C - help - If you say yes here you get support for hardware monitoring - capabilities of the following Maxim System Manager chips. - MAX16065 - MAX16066 - MAX16067 - MAX16068 - MAX16070 - MAX16071 - - This driver can also be built as a module. If so, the module - will be called max16065. - -config SENSORS_MAX1619 - tristate "Maxim MAX1619 sensor chip" - depends on I2C - help - If you say yes here you get support for MAX1619 sensor chip. - - This driver can also be built as a module. If so, the module - will be called max1619. - -config SENSORS_MAX1668 - tristate "Maxim MAX1668 and compatibles" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for MAX1668, MAX1989 and - MAX1805 chips. - - This driver can also be built as a module. If so, the module - will be called max1668. - -config SENSORS_MAX6639 - tristate "Maxim MAX6639 sensor chip" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the MAX6639 - sensor chips. - - This driver can also be built as a module. If so, the module - will be called max6639. - -config SENSORS_MAX6642 - tristate "Maxim MAX6642 sensor chip" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for MAX6642 sensor chip. - MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor - with Overtemperature Alarm from Maxim. - - This driver can also be built as a module. If so, the module - will be called max6642. - -config SENSORS_MAX6650 - tristate "Maxim MAX6650 sensor chip" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the MAX6650 / MAX6651 - sensor chips. - - This driver can also be built as a module. If so, the module - will be called max6650. - -config SENSORS_MCP3021 - tristate "Microchip MCP3021" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the MCP3021 chip - that is a A/D converter (ADC) with 10-bit resolution. - - This driver can also be built as a module. If so, the module - will be called mcp3021. - -config SENSORS_NTC_THERMISTOR - tristate "NTC thermistor support" - depends on EXPERIMENTAL - help - This driver supports NTC thermistors sensor reading and its - interpretation. The driver can also monitor the temperature and - send notifications about the temperature. - - Currently, this driver supports - NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333. - - This driver can also be built as a module. If so, the module - will be called ntc-thermistor. - -config SENSORS_PC87360 - tristate "National Semiconductor PC87360 family" - depends on !PPC - select HWMON_VID - help - If you say yes here you get access to the hardware monitoring - functions of the National Semiconductor PC8736x Super-I/O chips. - The PC87360, PC87363 and PC87364 only have fan monitoring and - control. The PC87365 and PC87366 additionally have voltage and - temperature monitoring. - - This driver can also be built as a module. If so, the module - will be called pc87360. - -config SENSORS_PC87427 - tristate "National Semiconductor PC87427" - depends on !PPC - help - If you say yes here you get access to the hardware monitoring - functions of the National Semiconductor PC87427 Super-I/O chip. - The chip has two distinct logical devices, one for fan speed - monitoring and control, and one for voltage and temperature - monitoring. Fan speed monitoring and control are supported, as - well as temperature monitoring. Voltages aren't supported yet. - - This driver can also be built as a module. If so, the module - will be called pc87427. - -config SENSORS_PCF8591 - tristate "Philips PCF8591 ADC/DAC" - depends on I2C - default n - help - If you say yes here you get support for Philips PCF8591 4-channel - ADC, 1-channel DAC chips. - - This driver can also be built as a module. If so, the module - will be called pcf8591. - - These devices are hard to detect and rarely found on mainstream - hardware. If unsure, say N. - -source drivers/hwmon/pmbus/Kconfig - -config SENSORS_SHT15 - tristate "Sensiron humidity and temperature sensors. SHT15 and compat." - depends on GPIOLIB - help - If you say yes here you get support for the Sensiron SHT10, SHT11, - SHT15, SHT71, SHT75 humidity and temperature sensors. - - This driver can also be built as a module. If so, the module - will be called sht15. - -config SENSORS_SHT21 - tristate "Sensiron humidity and temperature sensors. SHT21 and compat." - depends on I2C - help - If you say yes here you get support for the Sensiron SHT21, SHT25 - humidity and temperature sensors. - - This driver can also be built as a module. If so, the module - will be called sht21. - -config SENSORS_S3C - tristate "Samsung built-in ADC" - depends on S3C_ADC - help - If you say yes here you get support for the on-board ADCs of - the Samsung S3C24XX, S3C64XX and other series of SoC - - This driver can also be built as a module. If so, the module - will be called s3c-hwmon. - -config SENSORS_S3C_RAW - bool "Include raw channel attributes in sysfs" - depends on SENSORS_S3C - help - Say Y here if you want to include raw copies of all the ADC - channels in sysfs. - -config SENSORS_SIS5595 - tristate "Silicon Integrated Systems Corp. SiS5595" - depends on PCI - help - If you say yes here you get support for the integrated sensors in - SiS5595 South Bridges. - - This driver can also be built as a module. If so, the module - will be called sis5595. - -config SENSORS_SMM665 - tristate "Summit Microelectronics SMM665" - depends on I2C && EXPERIMENTAL - default n - help - If you say yes here you get support for the hardware monitoring - features of the Summit Microelectronics SMM665/SMM665B Six-Channel - Active DC Output Controller / Monitor. - - Other supported chips are SMM465, SMM665C, SMM764, and SMM766. - Support for those chips is untested. - - This driver can also be built as a module. If so, the module will - be called smm665. - -config SENSORS_DME1737 - tristate "SMSC DME1737, SCH311x and compatibles" - depends on I2C && EXPERIMENTAL && !PPC - select HWMON_VID - help - If you say yes here you get support for the hardware monitoring - and fan control features of the SMSC DME1737, SCH311x, SCH5027, and - Asus A8000 Super-I/O chips. - - This driver can also be built as a module. If so, the module - will be called dme1737. - -config SENSORS_EMC1403 - tristate "SMSC EMC1403/23 thermal sensor" - depends on I2C - help - If you say yes here you get support for the SMSC EMC1403/23 - temperature monitoring chip. - - Threshold values can be configured using sysfs. - Data from the different diodes are accessible via sysfs. - -config SENSORS_EMC2103 - tristate "SMSC EMC2103" - depends on I2C - help - If you say yes here you get support for the temperature - and fan sensors of the SMSC EMC2103 chips. - - This driver can also be built as a module. If so, the module - will be called emc2103. - -config SENSORS_EMC6W201 - tristate "SMSC EMC6W201" - depends on I2C - help - If you say yes here you get support for the SMSC EMC6W201 - hardware monitoring chip. - - This driver can also be built as a module. If so, the module - will be called emc6w201. - -config SENSORS_SMSC47M1 - tristate "SMSC LPC47M10x and compatibles" - depends on !PPC - help - If you say yes here you get support for the integrated fan - monitoring and control capabilities of the SMSC LPC47B27x, - LPC47M10x, LPC47M112, LPC47M13x, LPC47M14x, LPC47M15x, - LPC47M192, LPC47M292 and LPC47M997 chips. - - The temperature and voltage sensor features of the LPC47M15x, - LPC47M192, LPC47M292 and LPC47M997 are supported by another - driver, select also "SMSC LPC47M192 and compatibles" below for - those. - - This driver can also be built as a module. If so, the module - will be called smsc47m1. - -config SENSORS_SMSC47M192 - tristate "SMSC LPC47M192 and compatibles" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for the temperature and - voltage sensors of the SMSC LPC47M192, LPC47M15x, LPC47M292 - and LPC47M997 chips. - - The fan monitoring and control capabilities of these chips - are supported by another driver, select - "SMSC LPC47M10x and compatibles" above. You need both drivers - if you want fan control and voltage/temperature sensor support. - - This driver can also be built as a module. If so, the module - will be called smsc47m192. - -config SENSORS_SMSC47B397 - tristate "SMSC LPC47B397-NC" - depends on EXPERIMENTAL && !PPC - help - If you say yes here you get support for the SMSC LPC47B397-NC - sensor chip. - - This driver can also be built as a module. If so, the module - will be called smsc47b397. - -config SENSORS_SCH56XX_COMMON - tristate - default n - -config SENSORS_SCH5627 - tristate "SMSC SCH5627" - depends on !PPC - select SENSORS_SCH56XX_COMMON - help - If you say yes here you get support for the hardware monitoring - features of the SMSC SCH5627 Super-I/O chip including support for - the integrated watchdog. - - This driver can also be built as a module. If so, the module - will be called sch5627. - -config SENSORS_SCH5636 - tristate "SMSC SCH5636" - depends on !PPC - select SENSORS_SCH56XX_COMMON - help - SMSC SCH5636 Super I/O chips include an embedded microcontroller for - hardware monitoring solutions, allowing motherboard manufacturers to - create their own custom hwmon solution based upon the SCH5636. - - Currently this driver only supports the Fujitsu Theseus SCH5636 based - hwmon solution. Say yes here if you want support for the Fujitsu - Theseus' hardware monitoring features including support for the - integrated watchdog. - - This driver can also be built as a module. If so, the module - will be called sch5636. - -config SENSORS_ADS1015 - tristate "Texas Instruments ADS1015" - depends on I2C - help - If you say yes here you get support for Texas Instruments ADS1015 - 12-bit 4-input ADC device. - - This driver can also be built as a module. If so, the module - will be called ads1015. - -config SENSORS_ADS7828 - tristate "Texas Instruments ADS7828" - depends on I2C - help - If you say yes here you get support for Texas Instruments ADS7828 - 12-bit 8-channel ADC device. - - This driver can also be built as a module. If so, the module - will be called ads7828. - -config SENSORS_ADS7871 - tristate "Texas Instruments ADS7871 A/D converter" - depends on SPI - help - If you say yes here you get support for TI ADS7871 & ADS7870 - - This driver can also be built as a module. If so, the module - will be called ads7871. - -config SENSORS_AMC6821 - tristate "Texas Instruments AMC6821" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Texas Instruments - AMC6821 hardware monitoring chips. - - This driver can also be build as a module. If so, the module - will be called amc6821. - -config SENSORS_THMC50 - tristate "Texas Instruments THMC50 / Analog Devices ADM1022" - depends on I2C - help - If you say yes here you get support for Texas Instruments THMC50 - sensor chips and clones: the Analog Devices ADM1022. - - This driver can also be built as a module. If so, the module - will be called thmc50. - -config SENSORS_TMP102 - tristate "Texas Instruments TMP102" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for Texas Instruments TMP102 - sensor chips. - - This driver can also be built as a module. If so, the module - will be called tmp102. - -config SENSORS_TMP401 - tristate "Texas Instruments TMP401 and compatibles" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for Texas Instruments TMP401 and - TMP411 temperature sensor chips. - - This driver can also be built as a module. If so, the module - will be called tmp401. - -config SENSORS_TMP421 - tristate "Texas Instruments TMP421 and compatible" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for Texas Instruments TMP421, - TMP422 and TMP423 temperature sensor chips. - - This driver can also be built as a module. If so, the module - will be called tmp421. - -config SENSORS_TWL4030_MADC - tristate "Texas Instruments TWL4030 MADC Hwmon" - depends on TWL4030_MADC - help - If you say yes here you get hwmon support for triton - TWL4030-MADC. - - This driver can also be built as a module. If so it will be called - twl4030-madc-hwmon. - -config SENSORS_VIA_CPUTEMP - tristate "VIA CPU temperature sensor" - depends on X86 - select HWMON_VID - help - If you say yes here you get support for the temperature - sensor inside your CPU. Supported are all known variants of - the VIA C7 and Nano. - -config SENSORS_VIA686A - tristate "VIA686A" - depends on PCI - help - If you say yes here you get support for the integrated sensors in - Via 686A/B South Bridges. - - This driver can also be built as a module. If so, the module - will be called via686a. - -config SENSORS_VT1211 - tristate "VIA VT1211" - depends on !PPC - select HWMON_VID - help - If you say yes here then you get support for hardware monitoring - features of the VIA VT1211 Super-I/O chip. - - This driver can also be built as a module. If so, the module - will be called vt1211. - -config SENSORS_VT8231 - tristate "VIA VT8231" - depends on PCI - select HWMON_VID - help - If you say yes here then you get support for the integrated sensors - in the VIA VT8231 device. - - This driver can also be built as a module. If so, the module - will be called vt8231. - -config SENSORS_W83781D - tristate "Winbond W83781D, W83782D, W83783S, Asus AS99127F" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for the Winbond W8378x series - of sensor chips: the W83781D, W83782D and W83783S, and the similar - Asus AS99127F. - - This driver can also be built as a module. If so, the module - will be called w83781d. - -config SENSORS_W83791D - tristate "Winbond W83791D" - depends on I2C - select HWMON_VID - help - If you say yes here you get support for the Winbond W83791D chip. - - This driver can also be built as a module. If so, the module - will be called w83791d. - -config SENSORS_W83792D - tristate "Winbond W83792D" - depends on I2C - help - If you say yes here you get support for the Winbond W83792D chip. - - This driver can also be built as a module. If so, the module - will be called w83792d. - -config SENSORS_W83793 - tristate "Winbond W83793" - depends on I2C && EXPERIMENTAL - select HWMON_VID - help - If you say yes here you get support for the Winbond W83793 - hardware monitoring chip, including support for the integrated - watchdog. - - This driver can also be built as a module. If so, the module - will be called w83793. - -config SENSORS_W83795 - tristate "Winbond/Nuvoton W83795G/ADG" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Winbond W83795G and - W83795ADG hardware monitoring chip, including manual fan speed - control. - - This driver can also be built as a module. If so, the module - will be called w83795. - -config SENSORS_W83795_FANCTRL - boolean "Include automatic fan control support (DANGEROUS)" - depends on SENSORS_W83795 && EXPERIMENTAL - default n - help - If you say yes here, support for automatic fan speed control - will be included in the driver. - - This part of the code wasn't carefully reviewed and tested yet, - so enabling this option is strongly discouraged on production - servers. Only developers and testers should enable it for the - time being. - - Please also note that this option will create sysfs attribute - files which may change in the future, so you shouldn't rely - on them being stable. - -config SENSORS_W83L785TS - tristate "Winbond W83L785TS-S" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Winbond W83L785TS-S - sensor chip, which is used on the Asus A7N8X, among other - motherboards. - - This driver can also be built as a module. If so, the module - will be called w83l785ts. - -config SENSORS_W83L786NG - tristate "Winbond W83L786NG, W83L786NR" - depends on I2C && EXPERIMENTAL - help - If you say yes here you get support for the Winbond W83L786NG - and W83L786NR sensor chips. - - This driver can also be built as a module. If so, the module - will be called w83l786ng. - -config SENSORS_W83627HF - tristate "Winbond W83627HF, W83627THF, W83637HF, W83687THF, W83697HF" - depends on !PPC - select HWMON_VID - help - If you say yes here you get support for the Winbond W836X7 series - of sensor chips: the W83627HF, W83627THF, W83637HF, W83687THF and - W83697HF. - - This driver can also be built as a module. If so, the module - will be called w83627hf. - -config SENSORS_W83627EHF - tristate "Winbond W83627EHF/EHG/DHG/UHG, W83667HG, NCT6775F, NCT6776F" - depends on !PPC - select HWMON_VID - help - If you say yes here you get support for the hardware - monitoring functionality of the Winbond W83627EHF Super-I/O chip. - - This driver also supports the W83627EHG, which is the lead-free - version of the W83627EHF, and the W83627DHG, which is a similar - chip suited for specific Intel processors that use PECI such as - the Core 2 Duo. And also the W83627UHG, which is a stripped down - version of the W83627DHG (as far as hardware monitoring goes.) - - This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F - (also known as W83667HG-I), and NCT6776F. - - This driver can also be built as a module. If so, the module - will be called w83627ehf. - -config SENSORS_WM831X - tristate "WM831x PMICs" - depends on MFD_WM831X - help - If you say yes here you get support for the hardware - monitoring functionality of the Wolfson Microelectronics - WM831x series of PMICs. - - This driver can also be built as a module. If so, the module - will be called wm831x-hwmon. - -config SENSORS_WM8350 - tristate "Wolfson Microelectronics WM835x" - depends on MFD_WM8350 - help - If you say yes here you get support for the hardware - monitoring features of the WM835x series of PMICs. - - This driver can also be built as a module. If so, the module - will be called wm8350-hwmon. - -config SENSORS_ULTRA45 - tristate "Sun Ultra45 PIC16F747" - depends on SPARC64 - help - This driver provides support for the Ultra45 workstation environmental - sensors. - -config SENSORS_APPLESMC - tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)" - depends on INPUT && X86 - select NEW_LEDS - select LEDS_CLASS - select INPUT_POLLDEV - default n - help - This driver provides support for the Apple System Management - Controller, which provides an accelerometer (Apple Sudden Motion - Sensor), light sensors, temperature sensors, keyboard backlight - control and fan control. - - Only Intel-based Apple's computers are supported (MacBook Pro, - MacBook, MacMini). - - Data from the different sensors, keyboard backlight control and fan - control are accessible via sysfs. - - This driver also provides an absolute input class device, allowing - the laptop to act as a pinball machine-esque joystick. - - Say Y here if you have an applicable laptop and want to experience - the awesome power of applesmc. - -config SENSORS_MC13783_ADC - tristate "Freescale MC13783/MC13892 ADC" - depends on MFD_MC13XXX - help - Support for the A/D converter on MC13783 and MC13892 PMIC. - -if ACPI - -comment "ACPI drivers" - -config SENSORS_ACPI_POWER - tristate "ACPI 4.0 power meter" - help - This driver exposes ACPI 4.0 power meters as hardware monitoring - devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware - and a power meter. - - To compile this driver as a module, choose M here: - the module will be called acpi_power_meter. - -config SENSORS_ATK0110 - tristate "ASUS ATK0110" - depends on X86 && EXPERIMENTAL - help - If you say yes here you get support for the ACPI hardware - monitoring interface found in many ASUS motherboards. This - driver will provide readings of fans, voltages and temperatures - through the system firmware. - - This driver can also be built as a module. If so, the module - will be called asus_atk0110. - -endif # ACPI - -endif # HWMON diff --git a/ANDROID_3.4.5/drivers/hwmon/Makefile b/ANDROID_3.4.5/drivers/hwmon/Makefile deleted file mode 100644 index 6d3f11f7..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/Makefile +++ /dev/null @@ -1,133 +0,0 @@ -# -# Makefile for sensor chip drivers. -# - -obj-$(CONFIG_HWMON) += hwmon.o -obj-$(CONFIG_HWMON_VID) += hwmon-vid.o - -# APCI drivers -obj-$(CONFIG_SENSORS_ACPI_POWER) += acpi_power_meter.o -obj-$(CONFIG_SENSORS_ATK0110) += asus_atk0110.o - -# Native drivers -# asb100, then w83781d go first, as they can override other drivers' addresses. -obj-$(CONFIG_SENSORS_ASB100) += asb100.o -obj-$(CONFIG_SENSORS_W83627HF) += w83627hf.o -obj-$(CONFIG_SENSORS_W83792D) += w83792d.o -obj-$(CONFIG_SENSORS_W83793) += w83793.o -obj-$(CONFIG_SENSORS_W83795) += w83795.o -obj-$(CONFIG_SENSORS_W83781D) += w83781d.o -obj-$(CONFIG_SENSORS_W83791D) += w83791d.o - -obj-$(CONFIG_SENSORS_ABITUGURU) += abituguru.o -obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o -obj-$(CONFIG_SENSORS_AD7314) += ad7314.o -obj-$(CONFIG_SENSORS_AD7414) += ad7414.o -obj-$(CONFIG_SENSORS_AD7418) += ad7418.o -obj-$(CONFIG_SENSORS_ADCXX) += adcxx.o -obj-$(CONFIG_SENSORS_ADM1021) += adm1021.o -obj-$(CONFIG_SENSORS_ADM1025) += adm1025.o -obj-$(CONFIG_SENSORS_ADM1026) += adm1026.o -obj-$(CONFIG_SENSORS_ADM1029) += adm1029.o -obj-$(CONFIG_SENSORS_ADM1031) += adm1031.o -obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o -obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o -obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o -obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o -obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o -obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o -obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o -obj-$(CONFIG_SENSORS_ADT7475) += adt7475.o -obj-$(CONFIG_SENSORS_APPLESMC) += applesmc.o -obj-$(CONFIG_SENSORS_ASC7621) += asc7621.o -obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o -obj-$(CONFIG_SENSORS_CORETEMP) += coretemp.o -obj-$(CONFIG_SENSORS_DME1737) += dme1737.o -obj-$(CONFIG_SENSORS_DS620) += ds620.o -obj-$(CONFIG_SENSORS_DS1621) += ds1621.o -obj-$(CONFIG_SENSORS_EMC1403) += emc1403.o -obj-$(CONFIG_SENSORS_EMC2103) += emc2103.o -obj-$(CONFIG_SENSORS_EMC6W201) += emc6w201.o -obj-$(CONFIG_SENSORS_EXYNOS4_TMU) += exynos4_tmu.o -obj-$(CONFIG_SENSORS_F71805F) += f71805f.o -obj-$(CONFIG_SENSORS_F71882FG) += f71882fg.o -obj-$(CONFIG_SENSORS_F75375S) += f75375s.o -obj-$(CONFIG_SENSORS_FAM15H_POWER) += fam15h_power.o -obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o -obj-$(CONFIG_SENSORS_G760A) += g760a.o -obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o -obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o -obj-$(CONFIG_SENSORS_GPIO_FAN) += gpio-fan.o -obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o -obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o -obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o -obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o -obj-$(CONFIG_SENSORS_IT87) += it87.o -obj-$(CONFIG_SENSORS_JC42) += jc42.o -obj-$(CONFIG_SENSORS_JZ4740) += jz4740-hwmon.o -obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o -obj-$(CONFIG_SENSORS_K10TEMP) += k10temp.o -obj-$(CONFIG_SENSORS_LINEAGE) += lineage-pem.o -obj-$(CONFIG_SENSORS_LM63) += lm63.o -obj-$(CONFIG_SENSORS_LM70) += lm70.o -obj-$(CONFIG_SENSORS_LM73) += lm73.o -obj-$(CONFIG_SENSORS_LM75) += lm75.o -obj-$(CONFIG_SENSORS_LM77) += lm77.o -obj-$(CONFIG_SENSORS_LM78) += lm78.o -obj-$(CONFIG_SENSORS_LM80) += lm80.o -obj-$(CONFIG_SENSORS_LM83) += lm83.o -obj-$(CONFIG_SENSORS_LM85) += lm85.o -obj-$(CONFIG_SENSORS_LM87) += lm87.o -obj-$(CONFIG_SENSORS_LM90) += lm90.o -obj-$(CONFIG_SENSORS_LM92) += lm92.o -obj-$(CONFIG_SENSORS_LM93) += lm93.o -obj-$(CONFIG_SENSORS_LM95241) += lm95241.o -obj-$(CONFIG_SENSORS_LM95245) += lm95245.o -obj-$(CONFIG_SENSORS_LTC4151) += ltc4151.o -obj-$(CONFIG_SENSORS_LTC4215) += ltc4215.o -obj-$(CONFIG_SENSORS_LTC4245) += ltc4245.o -obj-$(CONFIG_SENSORS_LTC4261) += ltc4261.o -obj-$(CONFIG_SENSORS_MAX1111) += max1111.o -obj-$(CONFIG_SENSORS_MAX16065) += max16065.o -obj-$(CONFIG_SENSORS_MAX1619) += max1619.o -obj-$(CONFIG_SENSORS_MAX1668) += max1668.o -obj-$(CONFIG_SENSORS_MAX6639) += max6639.o -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_NTC_THERMISTOR) += ntc_thermistor.o -obj-$(CONFIG_SENSORS_PC87360) += pc87360.o -obj-$(CONFIG_SENSORS_PC87427) += pc87427.o -obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o -obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o -obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o -obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o -obj-$(CONFIG_SENSORS_SCH5636) += sch5636.o -obj-$(CONFIG_SENSORS_SHT15) += sht15.o -obj-$(CONFIG_SENSORS_SHT21) += sht21.o -obj-$(CONFIG_SENSORS_SIS5595) += sis5595.o -obj-$(CONFIG_SENSORS_SMM665) += smm665.o -obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o -obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o -obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o -obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o -obj-$(CONFIG_SENSORS_THMC50) += thmc50.o -obj-$(CONFIG_SENSORS_TMP102) += tmp102.o -obj-$(CONFIG_SENSORS_TMP401) += tmp401.o -obj-$(CONFIG_SENSORS_TMP421) += tmp421.o -obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o -obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o -obj-$(CONFIG_SENSORS_VIA686A) += via686a.o -obj-$(CONFIG_SENSORS_VT1211) += vt1211.o -obj-$(CONFIG_SENSORS_VT8231) += vt8231.o -obj-$(CONFIG_SENSORS_W83627EHF) += w83627ehf.o -obj-$(CONFIG_SENSORS_W83L785TS) += w83l785ts.o -obj-$(CONFIG_SENSORS_W83L786NG) += w83l786ng.o -obj-$(CONFIG_SENSORS_WM831X) += wm831x-hwmon.o -obj-$(CONFIG_SENSORS_WM8350) += wm8350-hwmon.o - -obj-$(CONFIG_PMBUS) += pmbus/ - -ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG - diff --git a/ANDROID_3.4.5/drivers/hwmon/abituguru.c b/ANDROID_3.4.5/drivers/hwmon/abituguru.c deleted file mode 100644 index a72bf256..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/abituguru.c +++ /dev/null @@ -1,1646 +0,0 @@ -/* - * abituguru.c Copyright (c) 2005-2006 Hans de Goede - * - * 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. - */ -/* - * This driver supports the sensor part of the first and second revision of - * the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because - * of lack of specs the CPU/RAM voltage & frequency control is not supported! - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Banks */ -#define ABIT_UGURU_ALARM_BANK 0x20 /* 1x 3 bytes */ -#define ABIT_UGURU_SENSOR_BANK1 0x21 /* 16x volt and temp */ -#define ABIT_UGURU_FAN_PWM 0x24 /* 3x 5 bytes */ -#define ABIT_UGURU_SENSOR_BANK2 0x26 /* fans */ -/* max nr of sensors in bank1, a bank1 sensor can be in, temp or nc */ -#define ABIT_UGURU_MAX_BANK1_SENSORS 16 -/* - * Warning if you increase one of the 2 MAX defines below to 10 or higher you - * should adjust the belonging _NAMES_LENGTH macro for the 2 digit number! - */ -/* max nr of sensors in bank2, currently mb's with max 6 fans are known */ -#define ABIT_UGURU_MAX_BANK2_SENSORS 6 -/* max nr of pwm outputs, currently mb's with max 5 pwm outputs are known */ -#define ABIT_UGURU_MAX_PWMS 5 -/* uGuru sensor bank 1 flags */ /* Alarm if: */ -#define ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE 0x01 /* temp over warn */ -#define ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE 0x02 /* volt over max */ -#define ABIT_UGURU_VOLT_LOW_ALARM_ENABLE 0x04 /* volt under min */ -#define ABIT_UGURU_TEMP_HIGH_ALARM_FLAG 0x10 /* temp is over warn */ -#define ABIT_UGURU_VOLT_HIGH_ALARM_FLAG 0x20 /* volt is over max */ -#define ABIT_UGURU_VOLT_LOW_ALARM_FLAG 0x40 /* volt is under min */ -/* uGuru sensor bank 2 flags */ /* Alarm if: */ -#define ABIT_UGURU_FAN_LOW_ALARM_ENABLE 0x01 /* fan under min */ -/* uGuru sensor bank common flags */ -#define ABIT_UGURU_BEEP_ENABLE 0x08 /* beep if alarm */ -#define ABIT_UGURU_SHUTDOWN_ENABLE 0x80 /* shutdown if alarm */ -/* uGuru fan PWM (speed control) flags */ -#define ABIT_UGURU_FAN_PWM_ENABLE 0x80 /* enable speed control */ -/* Values used for conversion */ -#define ABIT_UGURU_FAN_MAX 15300 /* RPM */ -/* Bank1 sensor types */ -#define ABIT_UGURU_IN_SENSOR 0 -#define ABIT_UGURU_TEMP_SENSOR 1 -#define ABIT_UGURU_NC 2 -/* - * In many cases we need to wait for the uGuru to reach a certain status, most - * of the time it will reach this status within 30 - 90 ISA reads, and thus we - * can best busy wait. This define gives the total amount of reads to try. - */ -#define ABIT_UGURU_WAIT_TIMEOUT 125 -/* - * However sometimes older versions of the uGuru seem to be distracted and they - * do not respond for a long time. To handle this we sleep before each of the - * last ABIT_UGURU_WAIT_TIMEOUT_SLEEP tries. - */ -#define ABIT_UGURU_WAIT_TIMEOUT_SLEEP 5 -/* - * Normally all expected status in abituguru_ready, are reported after the - * first read, but sometimes not and we need to poll. - */ -#define ABIT_UGURU_READY_TIMEOUT 5 -/* Maximum 3 retries on timedout reads/writes, delay 200 ms before retrying */ -#define ABIT_UGURU_MAX_RETRIES 3 -#define ABIT_UGURU_RETRY_DELAY (HZ/5) -/* Maximum 2 timeouts in abituguru_update_device, iow 3 in a row is an error */ -#define ABIT_UGURU_MAX_TIMEOUTS 2 -/* utility macros */ -#define ABIT_UGURU_NAME "abituguru" -#define ABIT_UGURU_DEBUG(level, format, arg...) \ - if (level <= verbose) \ - printk(KERN_DEBUG ABIT_UGURU_NAME ": " format , ## arg) -/* Macros to help calculate the sysfs_names array length */ -/* - * sum of strlen of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0, - * in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0 - */ -#define ABITUGURU_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14) -/* - * sum of strlen of: temp??_input\0, temp??_max\0, temp??_crit\0, - * temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0 - */ -#define ABITUGURU_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16) -/* - * sum of strlen of: fan?_input\0, fan?_min\0, fan?_alarm\0, - * fan?_alarm_enable\0, fan?_beep\0, fan?_shutdown\0 - */ -#define ABITUGURU_FAN_NAMES_LENGTH (11 + 9 + 11 + 18 + 10 + 14) -/* - * sum of strlen of: pwm?_enable\0, pwm?_auto_channels_temp\0, - * pwm?_auto_point{1,2}_pwm\0, pwm?_auto_point{1,2}_temp\0 - */ -#define ABITUGURU_PWM_NAMES_LENGTH (12 + 24 + 2 * 21 + 2 * 22) -/* IN_NAMES_LENGTH > TEMP_NAMES_LENGTH so assume all bank1 sensors are in */ -#define ABITUGURU_SYSFS_NAMES_LENGTH ( \ - ABIT_UGURU_MAX_BANK1_SENSORS * ABITUGURU_IN_NAMES_LENGTH + \ - ABIT_UGURU_MAX_BANK2_SENSORS * ABITUGURU_FAN_NAMES_LENGTH + \ - ABIT_UGURU_MAX_PWMS * ABITUGURU_PWM_NAMES_LENGTH) - -/* - * All the macros below are named identical to the oguru and oguru2 programs - * reverse engineered by Olle Sandberg, hence the names might not be 100% - * logical. I could come up with better names, but I prefer keeping the names - * identical so that this driver can be compared with his work more easily. - */ -/* Two i/o-ports are used by uGuru */ -#define ABIT_UGURU_BASE 0x00E0 -/* Used to tell uGuru what to read and to read the actual data */ -#define ABIT_UGURU_CMD 0x00 -/* Mostly used to check if uGuru is busy */ -#define ABIT_UGURU_DATA 0x04 -#define ABIT_UGURU_REGION_LENGTH 5 -/* uGuru status' */ -#define ABIT_UGURU_STATUS_WRITE 0x00 /* Ready to be written */ -#define ABIT_UGURU_STATUS_READ 0x01 /* Ready to be read */ -#define ABIT_UGURU_STATUS_INPUT 0x08 /* More input */ -#define ABIT_UGURU_STATUS_READY 0x09 /* Ready to be written */ - -/* Constants */ -/* in (Volt) sensors go up to 3494 mV, temp to 255000 millidegrees Celsius */ -static const int abituguru_bank1_max_value[2] = { 3494, 255000 }; -/* - * Min / Max allowed values for sensor2 (fan) alarm threshold, these values - * correspond to 300-3000 RPM - */ -static const u8 abituguru_bank2_min_threshold = 5; -static const u8 abituguru_bank2_max_threshold = 50; -/* - * Register 0 is a bitfield, 1 and 2 are pwm settings (255 = 100%), 3 and 4 - * are temperature trip points. - */ -static const int abituguru_pwm_settings_multiplier[5] = { 0, 1, 1, 1000, 1000 }; -/* - * Min / Max allowed values for pwm_settings. Note: pwm1 (CPU fan) is a - * special case the minium allowed pwm% setting for this is 30% (77) on - * some MB's this special case is handled in the code! - */ -static const u8 abituguru_pwm_min[5] = { 0, 170, 170, 25, 25 }; -static const u8 abituguru_pwm_max[5] = { 0, 255, 255, 75, 75 }; - - -/* Insmod parameters */ -static bool force; -module_param(force, bool, 0); -MODULE_PARM_DESC(force, "Set to one to force detection."); -static int bank1_types[ABIT_UGURU_MAX_BANK1_SENSORS] = { -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -module_param_array(bank1_types, int, NULL, 0); -MODULE_PARM_DESC(bank1_types, "Bank1 sensortype autodetection override:\n" - " -1 autodetect\n" - " 0 volt sensor\n" - " 1 temp sensor\n" - " 2 not connected"); -static int fan_sensors; -module_param(fan_sensors, int, 0); -MODULE_PARM_DESC(fan_sensors, "Number of fan sensors on the uGuru " - "(0 = autodetect)"); -static int pwms; -module_param(pwms, int, 0); -MODULE_PARM_DESC(pwms, "Number of PWMs on the uGuru " - "(0 = autodetect)"); - -/* Default verbose is 2, since this driver is still in the testing phase */ -static int verbose = 2; -module_param(verbose, int, 0644); -MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\n" - " 0 normal output\n" - " 1 + verbose error reporting\n" - " 2 + sensors type probing info\n" - " 3 + retryable error reporting"); - - -/* - * For the Abit uGuru, we need to keep some data in memory. - * The structure is dynamically allocated, at the same time when a new - * abituguru device is allocated. - */ -struct abituguru_data { - struct device *hwmon_dev; /* hwmon registered device */ - struct mutex update_lock; /* protect access to data and uGuru */ - unsigned long last_updated; /* In jiffies */ - unsigned short addr; /* uguru base address */ - char uguru_ready; /* is the uguru in ready state? */ - unsigned char update_timeouts; /* - * number of update timeouts since last - * successful update - */ - - /* - * The sysfs attr and their names are generated automatically, for bank1 - * we cannot use a predefined array because we don't know beforehand - * of a sensor is a volt or a temp sensor, for bank2 and the pwms its - * easier todo things the same way. For in sensors we have 9 (temp 7) - * sysfs entries per sensor, for bank2 and pwms 6. - */ - struct sensor_device_attribute_2 sysfs_attr[ - ABIT_UGURU_MAX_BANK1_SENSORS * 9 + - ABIT_UGURU_MAX_BANK2_SENSORS * 6 + ABIT_UGURU_MAX_PWMS * 6]; - /* Buffer to store the dynamically generated sysfs names */ - char sysfs_names[ABITUGURU_SYSFS_NAMES_LENGTH]; - - /* Bank 1 data */ - /* number of and addresses of [0] in, [1] temp sensors */ - u8 bank1_sensors[2]; - u8 bank1_address[2][ABIT_UGURU_MAX_BANK1_SENSORS]; - u8 bank1_value[ABIT_UGURU_MAX_BANK1_SENSORS]; - /* - * This array holds 3 entries per sensor for the bank 1 sensor settings - * (flags, min, max for voltage / flags, warn, shutdown for temp). - */ - u8 bank1_settings[ABIT_UGURU_MAX_BANK1_SENSORS][3]; - /* - * Maximum value for each sensor used for scaling in mV/millidegrees - * Celsius. - */ - int bank1_max_value[ABIT_UGURU_MAX_BANK1_SENSORS]; - - /* Bank 2 data, ABIT_UGURU_MAX_BANK2_SENSORS entries for bank2 */ - u8 bank2_sensors; /* actual number of bank2 sensors found */ - u8 bank2_value[ABIT_UGURU_MAX_BANK2_SENSORS]; - u8 bank2_settings[ABIT_UGURU_MAX_BANK2_SENSORS][2]; /* flags, min */ - - /* Alarms 2 bytes for bank1, 1 byte for bank2 */ - u8 alarms[3]; - - /* Fan PWM (speed control) 5 bytes per PWM */ - u8 pwms; /* actual number of pwms found */ - u8 pwm_settings[ABIT_UGURU_MAX_PWMS][5]; -}; - -static const char *never_happen = "This should never happen."; -static const char *report_this = - "Please report this to the abituguru maintainer (see MAINTAINERS)"; - -/* wait till the uguru is in the specified state */ -static int abituguru_wait(struct abituguru_data *data, u8 state) -{ - int timeout = ABIT_UGURU_WAIT_TIMEOUT; - - while (inb_p(data->addr + ABIT_UGURU_DATA) != state) { - timeout--; - if (timeout == 0) - return -EBUSY; - /* - * sleep a bit before our last few tries, see the comment on - * this where ABIT_UGURU_WAIT_TIMEOUT_SLEEP is defined. - */ - if (timeout <= ABIT_UGURU_WAIT_TIMEOUT_SLEEP) - msleep(0); - } - return 0; -} - -/* Put the uguru in ready for input state */ -static int abituguru_ready(struct abituguru_data *data) -{ - int timeout = ABIT_UGURU_READY_TIMEOUT; - - if (data->uguru_ready) - return 0; - - /* Reset? / Prepare for next read/write cycle */ - outb(0x00, data->addr + ABIT_UGURU_DATA); - - /* Wait till the uguru is ready */ - if (abituguru_wait(data, ABIT_UGURU_STATUS_READY)) { - ABIT_UGURU_DEBUG(1, - "timeout exceeded waiting for ready state\n"); - return -EIO; - } - - /* Cmd port MUST be read now and should contain 0xAC */ - while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { - timeout--; - if (timeout == 0) { - ABIT_UGURU_DEBUG(1, - "CMD reg does not hold 0xAC after ready command\n"); - return -EIO; - } - msleep(0); - } - - /* - * After this the ABIT_UGURU_DATA port should contain - * ABIT_UGURU_STATUS_INPUT - */ - timeout = ABIT_UGURU_READY_TIMEOUT; - while (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) { - timeout--; - if (timeout == 0) { - ABIT_UGURU_DEBUG(1, - "state != more input after ready command\n"); - return -EIO; - } - msleep(0); - } - - data->uguru_ready = 1; - return 0; -} - -/* - * Send the bank and then sensor address to the uGuru for the next read/write - * cycle. This function gets called as the first part of a read/write by - * abituguru_read and abituguru_write. This function should never be - * called by any other function. - */ -static int abituguru_send_address(struct abituguru_data *data, - u8 bank_addr, u8 sensor_addr, int retries) -{ - /* - * assume the caller does error handling itself if it has not requested - * any retries, and thus be quiet. - */ - int report_errors = retries; - - for (;;) { - /* - * Make sure the uguru is ready and then send the bank address, - * after this the uguru is no longer "ready". - */ - if (abituguru_ready(data) != 0) - return -EIO; - outb(bank_addr, data->addr + ABIT_UGURU_DATA); - data->uguru_ready = 0; - - /* - * Wait till the uguru is ABIT_UGURU_STATUS_INPUT state again - * and send the sensor addr - */ - if (abituguru_wait(data, ABIT_UGURU_STATUS_INPUT)) { - if (retries) { - ABIT_UGURU_DEBUG(3, "timeout exceeded " - "waiting for more input state, %d " - "tries remaining\n", retries); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(ABIT_UGURU_RETRY_DELAY); - retries--; - continue; - } - if (report_errors) - ABIT_UGURU_DEBUG(1, "timeout exceeded " - "waiting for more input state " - "(bank: %d)\n", (int)bank_addr); - return -EBUSY; - } - outb(sensor_addr, data->addr + ABIT_UGURU_CMD); - return 0; - } -} - -/* - * Read count bytes from sensor sensor_addr in bank bank_addr and store the - * result in buf, retry the send address part of the read retries times. - */ -static int abituguru_read(struct abituguru_data *data, - u8 bank_addr, u8 sensor_addr, u8 *buf, int count, int retries) -{ - int i; - - /* Send the address */ - i = abituguru_send_address(data, bank_addr, sensor_addr, retries); - if (i) - return i; - - /* And read the data */ - for (i = 0; i < count; i++) { - if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { - ABIT_UGURU_DEBUG(retries ? 1 : 3, - "timeout exceeded waiting for " - "read state (bank: %d, sensor: %d)\n", - (int)bank_addr, (int)sensor_addr); - break; - } - buf[i] = inb(data->addr + ABIT_UGURU_CMD); - } - - /* Last put the chip back in ready state */ - abituguru_ready(data); - - return i; -} - -/* - * Write count bytes from buf to sensor sensor_addr in bank bank_addr, the send - * address part of the write is always retried ABIT_UGURU_MAX_RETRIES times. - */ -static int abituguru_write(struct abituguru_data *data, - u8 bank_addr, u8 sensor_addr, u8 *buf, int count) -{ - /* - * We use the ready timeout as we have to wait for 0xAC just like the - * ready function - */ - int i, timeout = ABIT_UGURU_READY_TIMEOUT; - - /* Send the address */ - i = abituguru_send_address(data, bank_addr, sensor_addr, - ABIT_UGURU_MAX_RETRIES); - if (i) - return i; - - /* And write the data */ - for (i = 0; i < count; i++) { - if (abituguru_wait(data, ABIT_UGURU_STATUS_WRITE)) { - ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for " - "write state (bank: %d, sensor: %d)\n", - (int)bank_addr, (int)sensor_addr); - break; - } - outb(buf[i], data->addr + ABIT_UGURU_CMD); - } - - /* - * Now we need to wait till the chip is ready to be read again, - * so that we can read 0xAC as confirmation that our write has - * succeeded. - */ - if (abituguru_wait(data, ABIT_UGURU_STATUS_READ)) { - ABIT_UGURU_DEBUG(1, "timeout exceeded waiting for read state " - "after write (bank: %d, sensor: %d)\n", (int)bank_addr, - (int)sensor_addr); - return -EIO; - } - - /* Cmd port MUST be read now and should contain 0xAC */ - while (inb_p(data->addr + ABIT_UGURU_CMD) != 0xAC) { - timeout--; - if (timeout == 0) { - ABIT_UGURU_DEBUG(1, "CMD reg does not hold 0xAC after " - "write (bank: %d, sensor: %d)\n", - (int)bank_addr, (int)sensor_addr); - return -EIO; - } - msleep(0); - } - - /* Last put the chip back in ready state */ - abituguru_ready(data); - - return i; -} - -/* - * Detect sensor type. Temp and Volt sensors are enabled with - * different masks and will ignore enable masks not meant for them. - * This enables us to test what kind of sensor we're dealing with. - * By setting the alarm thresholds so that we will always get an - * alarm for sensor type X and then enabling the sensor as sensor type - * X, if we then get an alarm it is a sensor of type X. - */ -static int __devinit -abituguru_detect_bank1_sensor_type(struct abituguru_data *data, - u8 sensor_addr) -{ - u8 val, test_flag, buf[3]; - int i, ret = -ENODEV; /* error is the most common used retval :| */ - - /* If overriden by the user return the user selected type */ - if (bank1_types[sensor_addr] >= ABIT_UGURU_IN_SENSOR && - bank1_types[sensor_addr] <= ABIT_UGURU_NC) { - ABIT_UGURU_DEBUG(2, "assuming sensor type %d for bank1 sensor " - "%d because of \"bank1_types\" module param\n", - bank1_types[sensor_addr], (int)sensor_addr); - return bank1_types[sensor_addr]; - } - - /* First read the sensor and the current settings */ - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, sensor_addr, &val, - 1, ABIT_UGURU_MAX_RETRIES) != 1) - return -ENODEV; - - /* Test val is sane / usable for sensor type detection. */ - if ((val < 10u) || (val > 250u)) { - pr_warn("bank1-sensor: %d reading (%d) too close to limits, " - "unable to determine sensor type, skipping sensor\n", - (int)sensor_addr, (int)val); - /* - * assume no sensor is there for sensors for which we can't - * determine the sensor type because their reading is too close - * to their limits, this usually means no sensor is there. - */ - return ABIT_UGURU_NC; - } - - ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr); - /* - * Volt sensor test, enable volt low alarm, set min value ridicously - * high, or vica versa if the reading is very high. If its a volt - * sensor this should always give us an alarm. - */ - if (val <= 240u) { - buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE; - buf[1] = 245; - buf[2] = 250; - test_flag = ABIT_UGURU_VOLT_LOW_ALARM_FLAG; - } else { - buf[0] = ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE; - buf[1] = 5; - buf[2] = 10; - test_flag = ABIT_UGURU_VOLT_HIGH_ALARM_FLAG; - } - - if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, - buf, 3) != 3) - goto abituguru_detect_bank1_sensor_type_exit; - /* - * Now we need 20 ms to give the uguru time to read the sensors - * and raise a voltage alarm - */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/50); - /* Check for alarm and check the alarm is a volt low alarm. */ - if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, - ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; - if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, - sensor_addr, buf, 3, - ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; - if (buf[0] & test_flag) { - ABIT_UGURU_DEBUG(2, " found volt sensor\n"); - ret = ABIT_UGURU_IN_SENSOR; - goto abituguru_detect_bank1_sensor_type_exit; - } else - ABIT_UGURU_DEBUG(2, " alarm raised during volt " - "sensor test, but volt range flag not set\n"); - } else - ABIT_UGURU_DEBUG(2, " alarm not raised during volt sensor " - "test\n"); - - /* - * Temp sensor test, enable sensor as a temp sensor, set beep value - * ridicously low (but not too low, otherwise uguru ignores it). - * If its a temp sensor this should always give us an alarm. - */ - buf[0] = ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE; - buf[1] = 5; - buf[2] = 10; - if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr, - buf, 3) != 3) - goto abituguru_detect_bank1_sensor_type_exit; - /* - * Now we need 50 ms to give the uguru time to read the sensors - * and raise a temp alarm - */ - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(HZ/20); - /* Check for alarm and check the alarm is a temp high alarm. */ - if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, buf, 3, - ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; - if (buf[sensor_addr/8] & (0x01 << (sensor_addr % 8))) { - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, - sensor_addr, buf, 3, - ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_detect_bank1_sensor_type_exit; - if (buf[0] & ABIT_UGURU_TEMP_HIGH_ALARM_FLAG) { - ABIT_UGURU_DEBUG(2, " found temp sensor\n"); - ret = ABIT_UGURU_TEMP_SENSOR; - goto abituguru_detect_bank1_sensor_type_exit; - } else - ABIT_UGURU_DEBUG(2, " alarm raised during temp " - "sensor test, but temp high flag not set\n"); - } else - ABIT_UGURU_DEBUG(2, " alarm not raised during temp sensor " - "test\n"); - - ret = ABIT_UGURU_NC; -abituguru_detect_bank1_sensor_type_exit: - /* - * Restore original settings, failing here is really BAD, it has been - * reported that some BIOS-es hang when entering the uGuru menu with - * invalid settings present in the uGuru, so we try this 3 times. - */ - for (i = 0; i < 3; i++) - if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, - sensor_addr, data->bank1_settings[sensor_addr], - 3) == 3) - break; - if (i == 3) { - pr_err("Fatal error could not restore original settings. %s %s\n", - never_happen, report_this); - return -ENODEV; - } - return ret; -} - -/* - * These functions try to find out how many sensors there are in bank2 and how - * many pwms there are. The purpose of this is to make sure that we don't give - * the user the possibility to change settings for non-existent sensors / pwm. - * The uGuru will happily read / write whatever memory happens to be after the - * memory storing the PWM settings when reading/writing to a PWM which is not - * there. Notice even if we detect a PWM which doesn't exist we normally won't - * write to it, unless the user tries to change the settings. - * - * Although the uGuru allows reading (settings) from non existing bank2 - * sensors, my version of the uGuru does seem to stop writing to them, the - * write function above aborts in this case with: - * "CMD reg does not hold 0xAC after write" - * - * Notice these 2 tests are non destructive iow read-only tests, otherwise - * they would defeat their purpose. Although for the bank2_sensors detection a - * read/write test would be feasible because of the reaction above, I've - * however opted to stay on the safe side. - */ -static void __devinit -abituguru_detect_no_bank2_sensors(struct abituguru_data *data) -{ - int i; - - if (fan_sensors > 0 && fan_sensors <= ABIT_UGURU_MAX_BANK2_SENSORS) { - data->bank2_sensors = fan_sensors; - ABIT_UGURU_DEBUG(2, "assuming %d fan sensors because of " - "\"fan_sensors\" module param\n", - (int)data->bank2_sensors); - return; - } - - ABIT_UGURU_DEBUG(2, "detecting number of fan sensors\n"); - for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { - /* - * 0x89 are the known used bits: - * -0x80 enable shutdown - * -0x08 enable beep - * -0x01 enable alarm - * All other bits should be 0, but on some motherboards - * 0x40 (bit 6) is also high for some of the fans?? - */ - if (data->bank2_settings[i][0] & ~0xC9) { - ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " - "to be a fan sensor: settings[0] = %02X\n", - i, (unsigned int)data->bank2_settings[i][0]); - break; - } - - /* check if the threshold is within the allowed range */ - if (data->bank2_settings[i][1] < - abituguru_bank2_min_threshold) { - ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " - "to be a fan sensor: the threshold (%d) is " - "below the minimum (%d)\n", i, - (int)data->bank2_settings[i][1], - (int)abituguru_bank2_min_threshold); - break; - } - if (data->bank2_settings[i][1] > - abituguru_bank2_max_threshold) { - ABIT_UGURU_DEBUG(2, " bank2 sensor %d does not seem " - "to be a fan sensor: the threshold (%d) is " - "above the maximum (%d)\n", i, - (int)data->bank2_settings[i][1], - (int)abituguru_bank2_max_threshold); - break; - } - } - - data->bank2_sensors = i; - ABIT_UGURU_DEBUG(2, " found: %d fan sensors\n", - (int)data->bank2_sensors); -} - -static void __devinit -abituguru_detect_no_pwms(struct abituguru_data *data) -{ - int i, j; - - if (pwms > 0 && pwms <= ABIT_UGURU_MAX_PWMS) { - data->pwms = pwms; - ABIT_UGURU_DEBUG(2, "assuming %d PWM outputs because of " - "\"pwms\" module param\n", (int)data->pwms); - return; - } - - ABIT_UGURU_DEBUG(2, "detecting number of PWM outputs\n"); - for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { - /* - * 0x80 is the enable bit and the low - * nibble is which temp sensor to use, - * the other bits should be 0 - */ - if (data->pwm_settings[i][0] & ~0x8F) { - ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " - "to be a pwm channel: settings[0] = %02X\n", - i, (unsigned int)data->pwm_settings[i][0]); - break; - } - - /* - * the low nibble must correspond to one of the temp sensors - * we've found - */ - for (j = 0; j < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; - j++) { - if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][j] == - (data->pwm_settings[i][0] & 0x0F)) - break; - } - if (j == data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) { - ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " - "to be a pwm channel: %d is not a valid temp " - "sensor address\n", i, - data->pwm_settings[i][0] & 0x0F); - break; - } - - /* check if all other settings are within the allowed range */ - for (j = 1; j < 5; j++) { - u8 min; - /* special case pwm1 min pwm% */ - if ((i == 0) && ((j == 1) || (j == 2))) - min = 77; - else - min = abituguru_pwm_min[j]; - if (data->pwm_settings[i][j] < min) { - ABIT_UGURU_DEBUG(2, " pwm channel %d does " - "not seem to be a pwm channel: " - "setting %d (%d) is below the minimum " - "value (%d)\n", i, j, - (int)data->pwm_settings[i][j], - (int)min); - goto abituguru_detect_no_pwms_exit; - } - if (data->pwm_settings[i][j] > abituguru_pwm_max[j]) { - ABIT_UGURU_DEBUG(2, " pwm channel %d does " - "not seem to be a pwm channel: " - "setting %d (%d) is above the maximum " - "value (%d)\n", i, j, - (int)data->pwm_settings[i][j], - (int)abituguru_pwm_max[j]); - goto abituguru_detect_no_pwms_exit; - } - } - - /* check that min temp < max temp and min pwm < max pwm */ - if (data->pwm_settings[i][1] >= data->pwm_settings[i][2]) { - ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " - "to be a pwm channel: min pwm (%d) >= " - "max pwm (%d)\n", i, - (int)data->pwm_settings[i][1], - (int)data->pwm_settings[i][2]); - break; - } - if (data->pwm_settings[i][3] >= data->pwm_settings[i][4]) { - ABIT_UGURU_DEBUG(2, " pwm channel %d does not seem " - "to be a pwm channel: min temp (%d) >= " - "max temp (%d)\n", i, - (int)data->pwm_settings[i][3], - (int)data->pwm_settings[i][4]); - break; - } - } - -abituguru_detect_no_pwms_exit: - data->pwms = i; - ABIT_UGURU_DEBUG(2, " found: %d PWM outputs\n", (int)data->pwms); -} - -/* - * Following are the sysfs callback functions. These functions expect: - * sensor_device_attribute_2->index: sensor address/offset in the bank - * sensor_device_attribute_2->nr: register offset, bitmask or NA. - */ -static struct abituguru_data *abituguru_update_device(struct device *dev); - -static ssize_t show_bank1_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = abituguru_update_device(dev); - if (!data) - return -EIO; - return sprintf(buf, "%d\n", (data->bank1_value[attr->index] * - data->bank1_max_value[attr->index] + 128) / 255); -} - -static ssize_t show_bank1_setting(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - (data->bank1_settings[attr->index][attr->nr] * - data->bank1_max_value[attr->index] + 128) / 255); -} - -static ssize_t show_bank2_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = abituguru_update_device(dev); - if (!data) - return -EIO; - return sprintf(buf, "%d\n", (data->bank2_value[attr->index] * - ABIT_UGURU_FAN_MAX + 128) / 255); -} - -static ssize_t show_bank2_setting(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - (data->bank2_settings[attr->index][attr->nr] * - ABIT_UGURU_FAN_MAX + 128) / 255); -} - -static ssize_t store_bank1_setting(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - unsigned long val; - ssize_t ret; - - ret = kstrtoul(buf, 10, &val); - if (ret) - return ret; - - ret = count; - val = (val * 255 + data->bank1_max_value[attr->index] / 2) / - data->bank1_max_value[attr->index]; - if (val > 255) - return -EINVAL; - - mutex_lock(&data->update_lock); - if (data->bank1_settings[attr->index][attr->nr] != val) { - u8 orig_val = data->bank1_settings[attr->index][attr->nr]; - data->bank1_settings[attr->index][attr->nr] = val; - if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, - attr->index, data->bank1_settings[attr->index], - 3) <= attr->nr) { - data->bank1_settings[attr->index][attr->nr] = orig_val; - ret = -EIO; - } - } - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t store_bank2_setting(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - unsigned long val; - ssize_t ret; - - ret = kstrtoul(buf, 10, &val); - if (ret) - return ret; - - ret = count; - val = (val * 255 + ABIT_UGURU_FAN_MAX / 2) / ABIT_UGURU_FAN_MAX; - - /* this check can be done before taking the lock */ - if (val < abituguru_bank2_min_threshold || - val > abituguru_bank2_max_threshold) - return -EINVAL; - - mutex_lock(&data->update_lock); - if (data->bank2_settings[attr->index][attr->nr] != val) { - u8 orig_val = data->bank2_settings[attr->index][attr->nr]; - data->bank2_settings[attr->index][attr->nr] = val; - if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK2 + 2, - attr->index, data->bank2_settings[attr->index], - 2) <= attr->nr) { - data->bank2_settings[attr->index][attr->nr] = orig_val; - ret = -EIO; - } - } - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t show_bank1_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = abituguru_update_device(dev); - if (!data) - return -EIO; - /* - * See if the alarm bit for this sensor is set, and if the - * alarm matches the type of alarm we're looking for (for volt - * it can be either low or high). The type is stored in a few - * readonly bits in the settings part of the relevant sensor. - * The bitmask of the type is passed to us in attr->nr. - */ - if ((data->alarms[attr->index / 8] & (0x01 << (attr->index % 8))) && - (data->bank1_settings[attr->index][0] & attr->nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_bank2_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = abituguru_update_device(dev); - if (!data) - return -EIO; - if (data->alarms[2] & (0x01 << attr->index)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_bank1_mask(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - if (data->bank1_settings[attr->index][0] & attr->nr) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_bank2_mask(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - if (data->bank2_settings[attr->index][0] & attr->nr) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_bank1_mask(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - ssize_t ret; - u8 orig_val; - unsigned long mask; - - ret = kstrtoul(buf, 10, &mask); - if (ret) - return ret; - - ret = count; - mutex_lock(&data->update_lock); - orig_val = data->bank1_settings[attr->index][0]; - - if (mask) - data->bank1_settings[attr->index][0] |= attr->nr; - else - data->bank1_settings[attr->index][0] &= ~attr->nr; - - if ((data->bank1_settings[attr->index][0] != orig_val) && - (abituguru_write(data, - ABIT_UGURU_SENSOR_BANK1 + 2, attr->index, - data->bank1_settings[attr->index], 3) < 1)) { - data->bank1_settings[attr->index][0] = orig_val; - ret = -EIO; - } - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t store_bank2_mask(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - ssize_t ret; - u8 orig_val; - unsigned long mask; - - ret = kstrtoul(buf, 10, &mask); - if (ret) - return ret; - - ret = count; - mutex_lock(&data->update_lock); - orig_val = data->bank2_settings[attr->index][0]; - - if (mask) - data->bank2_settings[attr->index][0] |= attr->nr; - else - data->bank2_settings[attr->index][0] &= ~attr->nr; - - if ((data->bank2_settings[attr->index][0] != orig_val) && - (abituguru_write(data, - ABIT_UGURU_SENSOR_BANK2 + 2, attr->index, - data->bank2_settings[attr->index], 2) < 1)) { - data->bank2_settings[attr->index][0] = orig_val; - ret = -EIO; - } - mutex_unlock(&data->update_lock); - return ret; -} - -/* Fan PWM (speed control) */ -static ssize_t show_pwm_setting(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->pwm_settings[attr->index][attr->nr] * - abituguru_pwm_settings_multiplier[attr->nr]); -} - -static ssize_t store_pwm_setting(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - u8 min; - unsigned long val; - ssize_t ret; - - ret = kstrtoul(buf, 10, &val); - if (ret) - return ret; - - ret = count; - val = (val + abituguru_pwm_settings_multiplier[attr->nr] / 2) / - abituguru_pwm_settings_multiplier[attr->nr]; - - /* special case pwm1 min pwm% */ - if ((attr->index == 0) && ((attr->nr == 1) || (attr->nr == 2))) - min = 77; - else - min = abituguru_pwm_min[attr->nr]; - - /* this check can be done before taking the lock */ - if (val < min || val > abituguru_pwm_max[attr->nr]) - return -EINVAL; - - mutex_lock(&data->update_lock); - /* this check needs to be done after taking the lock */ - if ((attr->nr & 1) && - (val >= data->pwm_settings[attr->index][attr->nr + 1])) - ret = -EINVAL; - else if (!(attr->nr & 1) && - (val <= data->pwm_settings[attr->index][attr->nr - 1])) - ret = -EINVAL; - else if (data->pwm_settings[attr->index][attr->nr] != val) { - u8 orig_val = data->pwm_settings[attr->index][attr->nr]; - data->pwm_settings[attr->index][attr->nr] = val; - if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, - attr->index, data->pwm_settings[attr->index], - 5) <= attr->nr) { - data->pwm_settings[attr->index][attr->nr] = - orig_val; - ret = -EIO; - } - } - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t show_pwm_sensor(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - int i; - /* - * We need to walk to the temp sensor addresses to find what - * the userspace id of the configured temp sensor is. - */ - for (i = 0; i < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]; i++) - if (data->bank1_address[ABIT_UGURU_TEMP_SENSOR][i] == - (data->pwm_settings[attr->index][0] & 0x0F)) - return sprintf(buf, "%d\n", i+1); - - return -ENXIO; -} - -static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - ssize_t ret; - unsigned long val; - u8 orig_val; - u8 address; - - ret = kstrtoul(buf, 10, &val); - if (ret) - return ret; - - if (val == 0 || val > data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) - return -EINVAL; - - val -= 1; - ret = count; - mutex_lock(&data->update_lock); - orig_val = data->pwm_settings[attr->index][0]; - address = data->bank1_address[ABIT_UGURU_TEMP_SENSOR][val]; - data->pwm_settings[attr->index][0] &= 0xF0; - data->pwm_settings[attr->index][0] |= address; - if (data->pwm_settings[attr->index][0] != orig_val) { - if (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, attr->index, - data->pwm_settings[attr->index], 5) < 1) { - data->pwm_settings[attr->index][0] = orig_val; - ret = -EIO; - } - } - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - int res = 0; - if (data->pwm_settings[attr->index][0] & ABIT_UGURU_FAN_PWM_ENABLE) - res = 2; - return sprintf(buf, "%d\n", res); -} - -static ssize_t store_pwm_enable(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru_data *data = dev_get_drvdata(dev); - u8 orig_val; - ssize_t ret; - unsigned long user_val; - - ret = kstrtoul(buf, 10, &user_val); - if (ret) - return ret; - - ret = count; - mutex_lock(&data->update_lock); - orig_val = data->pwm_settings[attr->index][0]; - switch (user_val) { - case 0: - data->pwm_settings[attr->index][0] &= - ~ABIT_UGURU_FAN_PWM_ENABLE; - break; - case 2: - data->pwm_settings[attr->index][0] |= ABIT_UGURU_FAN_PWM_ENABLE; - break; - default: - ret = -EINVAL; - } - if ((data->pwm_settings[attr->index][0] != orig_val) && - (abituguru_write(data, ABIT_UGURU_FAN_PWM + 1, - attr->index, data->pwm_settings[attr->index], - 5) < 1)) { - data->pwm_settings[attr->index][0] = orig_val; - ret = -EIO; - } - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", ABIT_UGURU_NAME); -} - -/* Sysfs attr templates, the real entries are generated automatically. */ -static const -struct sensor_device_attribute_2 abituguru_sysfs_bank1_templ[2][9] = { - { - SENSOR_ATTR_2(in%d_input, 0444, show_bank1_value, NULL, 0, 0), - SENSOR_ATTR_2(in%d_min, 0644, show_bank1_setting, - store_bank1_setting, 1, 0), - SENSOR_ATTR_2(in%d_min_alarm, 0444, show_bank1_alarm, NULL, - ABIT_UGURU_VOLT_LOW_ALARM_FLAG, 0), - SENSOR_ATTR_2(in%d_max, 0644, show_bank1_setting, - store_bank1_setting, 2, 0), - SENSOR_ATTR_2(in%d_max_alarm, 0444, show_bank1_alarm, NULL, - ABIT_UGURU_VOLT_HIGH_ALARM_FLAG, 0), - SENSOR_ATTR_2(in%d_beep, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), - SENSOR_ATTR_2(in%d_shutdown, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), - SENSOR_ATTR_2(in%d_min_alarm_enable, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_VOLT_LOW_ALARM_ENABLE, 0), - SENSOR_ATTR_2(in%d_max_alarm_enable, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE, 0), - }, { - SENSOR_ATTR_2(temp%d_input, 0444, show_bank1_value, NULL, 0, 0), - SENSOR_ATTR_2(temp%d_alarm, 0444, show_bank1_alarm, NULL, - ABIT_UGURU_TEMP_HIGH_ALARM_FLAG, 0), - SENSOR_ATTR_2(temp%d_max, 0644, show_bank1_setting, - store_bank1_setting, 1, 0), - SENSOR_ATTR_2(temp%d_crit, 0644, show_bank1_setting, - store_bank1_setting, 2, 0), - SENSOR_ATTR_2(temp%d_beep, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_BEEP_ENABLE, 0), - SENSOR_ATTR_2(temp%d_shutdown, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), - SENSOR_ATTR_2(temp%d_alarm_enable, 0644, show_bank1_mask, - store_bank1_mask, ABIT_UGURU_TEMP_HIGH_ALARM_ENABLE, 0), - } -}; - -static const struct sensor_device_attribute_2 abituguru_sysfs_fan_templ[6] = { - SENSOR_ATTR_2(fan%d_input, 0444, show_bank2_value, NULL, 0, 0), - SENSOR_ATTR_2(fan%d_alarm, 0444, show_bank2_alarm, NULL, 0, 0), - SENSOR_ATTR_2(fan%d_min, 0644, show_bank2_setting, - store_bank2_setting, 1, 0), - SENSOR_ATTR_2(fan%d_beep, 0644, show_bank2_mask, - store_bank2_mask, ABIT_UGURU_BEEP_ENABLE, 0), - SENSOR_ATTR_2(fan%d_shutdown, 0644, show_bank2_mask, - store_bank2_mask, ABIT_UGURU_SHUTDOWN_ENABLE, 0), - SENSOR_ATTR_2(fan%d_alarm_enable, 0644, show_bank2_mask, - store_bank2_mask, ABIT_UGURU_FAN_LOW_ALARM_ENABLE, 0), -}; - -static const struct sensor_device_attribute_2 abituguru_sysfs_pwm_templ[6] = { - SENSOR_ATTR_2(pwm%d_enable, 0644, show_pwm_enable, - store_pwm_enable, 0, 0), - SENSOR_ATTR_2(pwm%d_auto_channels_temp, 0644, show_pwm_sensor, - store_pwm_sensor, 0, 0), - SENSOR_ATTR_2(pwm%d_auto_point1_pwm, 0644, show_pwm_setting, - store_pwm_setting, 1, 0), - SENSOR_ATTR_2(pwm%d_auto_point2_pwm, 0644, show_pwm_setting, - store_pwm_setting, 2, 0), - SENSOR_ATTR_2(pwm%d_auto_point1_temp, 0644, show_pwm_setting, - store_pwm_setting, 3, 0), - SENSOR_ATTR_2(pwm%d_auto_point2_temp, 0644, show_pwm_setting, - store_pwm_setting, 4, 0), -}; - -static struct sensor_device_attribute_2 abituguru_sysfs_attr[] = { - SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), -}; - -static int __devinit abituguru_probe(struct platform_device *pdev) -{ - struct abituguru_data *data; - int i, j, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV; - char *sysfs_filename; - - /* - * El weirdo probe order, to keep the sysfs order identical to the - * BIOS and window-appliction listing order. - */ - const u8 probe_order[ABIT_UGURU_MAX_BANK1_SENSORS] = { - 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02, - 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; - - data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - /* See if the uGuru is ready */ - if (inb_p(data->addr + ABIT_UGURU_DATA) == ABIT_UGURU_STATUS_INPUT) - data->uguru_ready = 1; - - /* - * Completely read the uGuru this has 2 purposes: - * - testread / see if one really is there. - * - make an in memory copy of all the uguru settings for future use. - */ - if (abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, - data->alarms, 3, ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_probe_error; - - for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, i, - &data->bank1_value[i], 1, - ABIT_UGURU_MAX_RETRIES) != 1) - goto abituguru_probe_error; - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK1+1, i, - data->bank1_settings[i], 3, - ABIT_UGURU_MAX_RETRIES) != 3) - goto abituguru_probe_error; - } - /* - * Note: We don't know how many bank2 sensors / pwms there really are, - * but in order to "detect" this we need to read the maximum amount - * anyways. If we read sensors/pwms not there we'll just read crap - * this can't hurt. We need the detection because we don't want - * unwanted writes, which will hurt! - */ - for (i = 0; i < ABIT_UGURU_MAX_BANK2_SENSORS; i++) { - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, - &data->bank2_value[i], 1, - ABIT_UGURU_MAX_RETRIES) != 1) - goto abituguru_probe_error; - if (abituguru_read(data, ABIT_UGURU_SENSOR_BANK2+1, i, - data->bank2_settings[i], 2, - ABIT_UGURU_MAX_RETRIES) != 2) - goto abituguru_probe_error; - } - for (i = 0; i < ABIT_UGURU_MAX_PWMS; i++) { - if (abituguru_read(data, ABIT_UGURU_FAN_PWM, i, - data->pwm_settings[i], 5, - ABIT_UGURU_MAX_RETRIES) != 5) - goto abituguru_probe_error; - } - data->last_updated = jiffies; - - /* Detect sensor types and fill the sysfs attr for bank1 */ - sysfs_attr_i = 0; - sysfs_filename = data->sysfs_names; - sysfs_names_free = ABITUGURU_SYSFS_NAMES_LENGTH; - for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { - res = abituguru_detect_bank1_sensor_type(data, probe_order[i]); - if (res < 0) - goto abituguru_probe_error; - if (res == ABIT_UGURU_NC) - continue; - - /* res 1 (temp) sensors have 7 sysfs entries, 0 (in) 9 */ - for (j = 0; j < (res ? 7 : 9); j++) { - used = snprintf(sysfs_filename, sysfs_names_free, - abituguru_sysfs_bank1_templ[res][j].dev_attr. - attr.name, data->bank1_sensors[res] + res) - + 1; - data->sysfs_attr[sysfs_attr_i] = - abituguru_sysfs_bank1_templ[res][j]; - data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = - sysfs_filename; - data->sysfs_attr[sysfs_attr_i].index = probe_order[i]; - sysfs_filename += used; - sysfs_names_free -= used; - sysfs_attr_i++; - } - data->bank1_max_value[probe_order[i]] = - abituguru_bank1_max_value[res]; - data->bank1_address[res][data->bank1_sensors[res]] = - probe_order[i]; - data->bank1_sensors[res]++; - } - /* Detect number of sensors and fill the sysfs attr for bank2 (fans) */ - abituguru_detect_no_bank2_sensors(data); - for (i = 0; i < data->bank2_sensors; i++) { - for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_fan_templ); j++) { - used = snprintf(sysfs_filename, sysfs_names_free, - abituguru_sysfs_fan_templ[j].dev_attr.attr.name, - i + 1) + 1; - data->sysfs_attr[sysfs_attr_i] = - abituguru_sysfs_fan_templ[j]; - data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = - sysfs_filename; - data->sysfs_attr[sysfs_attr_i].index = i; - sysfs_filename += used; - sysfs_names_free -= used; - sysfs_attr_i++; - } - } - /* Detect number of sensors and fill the sysfs attr for pwms */ - abituguru_detect_no_pwms(data); - for (i = 0; i < data->pwms; i++) { - for (j = 0; j < ARRAY_SIZE(abituguru_sysfs_pwm_templ); j++) { - used = snprintf(sysfs_filename, sysfs_names_free, - abituguru_sysfs_pwm_templ[j].dev_attr.attr.name, - i + 1) + 1; - data->sysfs_attr[sysfs_attr_i] = - abituguru_sysfs_pwm_templ[j]; - data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = - sysfs_filename; - data->sysfs_attr[sysfs_attr_i].index = i; - sysfs_filename += used; - sysfs_names_free -= used; - sysfs_attr_i++; - } - } - /* Fail safe check, this should never happen! */ - if (sysfs_names_free < 0) { - pr_err("Fatal error ran out of space for sysfs attr names. %s %s", - never_happen, report_this); - res = -ENAMETOOLONG; - goto abituguru_probe_error; - } - pr_info("found Abit uGuru\n"); - - /* Register sysfs hooks */ - for (i = 0; i < sysfs_attr_i; i++) - if (device_create_file(&pdev->dev, - &data->sysfs_attr[i].dev_attr)) - goto abituguru_probe_error; - for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) - if (device_create_file(&pdev->dev, - &abituguru_sysfs_attr[i].dev_attr)) - goto abituguru_probe_error; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; /* success */ - - res = PTR_ERR(data->hwmon_dev); -abituguru_probe_error: - for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) - device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) - device_remove_file(&pdev->dev, - &abituguru_sysfs_attr[i].dev_attr); - platform_set_drvdata(pdev, NULL); - kfree(data); - return res; -} - -static int __devexit abituguru_remove(struct platform_device *pdev) -{ - int i; - struct abituguru_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) - device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) - device_remove_file(&pdev->dev, - &abituguru_sysfs_attr[i].dev_attr); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static struct abituguru_data *abituguru_update_device(struct device *dev) -{ - int i, err; - struct abituguru_data *data = dev_get_drvdata(dev); - /* fake a complete successful read if no update necessary. */ - char success = 1; - - mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ)) { - success = 0; - err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0, - data->alarms, 3, 0); - if (err != 3) - goto LEAVE_UPDATE; - for (i = 0; i < ABIT_UGURU_MAX_BANK1_SENSORS; i++) { - err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1, - i, &data->bank1_value[i], 1, 0); - if (err != 1) - goto LEAVE_UPDATE; - err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1 + 1, - i, data->bank1_settings[i], 3, 0); - if (err != 3) - goto LEAVE_UPDATE; - } - for (i = 0; i < data->bank2_sensors; i++) { - err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK2, i, - &data->bank2_value[i], 1, 0); - if (err != 1) - goto LEAVE_UPDATE; - } - /* success! */ - success = 1; - data->update_timeouts = 0; -LEAVE_UPDATE: - /* handle timeout condition */ - if (!success && (err == -EBUSY || err >= 0)) { - /* No overflow please */ - if (data->update_timeouts < 255u) - data->update_timeouts++; - if (data->update_timeouts <= ABIT_UGURU_MAX_TIMEOUTS) { - ABIT_UGURU_DEBUG(3, "timeout exceeded, will " - "try again next update\n"); - /* Just a timeout, fake a successful read */ - success = 1; - } else - ABIT_UGURU_DEBUG(1, "timeout exceeded %d " - "times waiting for more input state\n", - (int)data->update_timeouts); - } - /* On success set last_updated */ - if (success) - data->last_updated = jiffies; - } - mutex_unlock(&data->update_lock); - - if (success) - return data; - else - return NULL; -} - -#ifdef CONFIG_PM -static int abituguru_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct abituguru_data *data = platform_get_drvdata(pdev); - /* - * make sure all communications with the uguru are done and no new - * ones are started - */ - mutex_lock(&data->update_lock); - return 0; -} - -static int abituguru_resume(struct platform_device *pdev) -{ - struct abituguru_data *data = platform_get_drvdata(pdev); - /* See if the uGuru is still ready */ - if (inb_p(data->addr + ABIT_UGURU_DATA) != ABIT_UGURU_STATUS_INPUT) - data->uguru_ready = 0; - mutex_unlock(&data->update_lock); - return 0; -} -#else -#define abituguru_suspend NULL -#define abituguru_resume NULL -#endif /* CONFIG_PM */ - -static struct platform_driver abituguru_driver = { - .driver = { - .owner = THIS_MODULE, - .name = ABIT_UGURU_NAME, - }, - .probe = abituguru_probe, - .remove = __devexit_p(abituguru_remove), - .suspend = abituguru_suspend, - .resume = abituguru_resume, -}; - -static int __init abituguru_detect(void) -{ - /* - * See if there is an uguru there. After a reboot uGuru will hold 0x00 - * at DATA and 0xAC, when this driver has already been loaded once - * DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either - * scenario but some will hold 0x00. - * Some uGuru's initially hold 0x09 at DATA and will only hold 0x08 - * after reading CMD first, so CMD must be read first! - */ - u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD); - u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA); - if (((data_val == 0x00) || (data_val == 0x08)) && - ((cmd_val == 0x00) || (cmd_val == 0xAC))) - return ABIT_UGURU_BASE; - - ABIT_UGURU_DEBUG(2, "no Abit uGuru found, data = 0x%02X, cmd = " - "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); - - if (force) { - pr_info("Assuming Abit uGuru is present because of \"force\" parameter\n"); - return ABIT_UGURU_BASE; - } - - /* No uGuru found */ - return -ENODEV; -} - -static struct platform_device *abituguru_pdev; - -static int __init abituguru_init(void) -{ - int address, err; - struct resource res = { .flags = IORESOURCE_IO }; - const char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); - - /* safety check, refuse to load on non Abit motherboards */ - if (!force && (!board_vendor || - strcmp(board_vendor, "http://www.abit.com.tw/"))) - return -ENODEV; - - address = abituguru_detect(); - if (address < 0) - return address; - - err = platform_driver_register(&abituguru_driver); - if (err) - goto exit; - - abituguru_pdev = platform_device_alloc(ABIT_UGURU_NAME, address); - if (!abituguru_pdev) { - pr_err("Device allocation failed\n"); - err = -ENOMEM; - goto exit_driver_unregister; - } - - res.start = address; - res.end = address + ABIT_UGURU_REGION_LENGTH - 1; - res.name = ABIT_UGURU_NAME; - - err = platform_device_add_resources(abituguru_pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add(abituguru_pdev); - if (err) { - pr_err("Device addition failed (%d)\n", err); - goto exit_device_put; - } - - return 0; - -exit_device_put: - platform_device_put(abituguru_pdev); -exit_driver_unregister: - platform_driver_unregister(&abituguru_driver); -exit: - return err; -} - -static void __exit abituguru_exit(void) -{ - platform_device_unregister(abituguru_pdev); - platform_driver_unregister(&abituguru_driver); -} - -MODULE_AUTHOR("Hans de Goede "); -MODULE_DESCRIPTION("Abit uGuru Sensor device"); -MODULE_LICENSE("GPL"); - -module_init(abituguru_init); -module_exit(abituguru_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/abituguru3.c b/ANDROID_3.4.5/drivers/hwmon/abituguru3.c deleted file mode 100644 index a5bc4287..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/abituguru3.c +++ /dev/null @@ -1,1322 +0,0 @@ -/* - * abituguru3.c - * - * Copyright (c) 2006-2008 Hans de Goede - * Copyright (c) 2008 Alistair John Strachan - * - * 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. - */ -/* - * This driver supports the sensor part of revision 3 of the custom Abit uGuru - * chip found on newer Abit uGuru motherboards. Note: because of lack of specs - * only reading the sensors and their settings is supported. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* uGuru3 bank addresses */ -#define ABIT_UGURU3_SETTINGS_BANK 0x01 -#define ABIT_UGURU3_SENSORS_BANK 0x08 -#define ABIT_UGURU3_MISC_BANK 0x09 -#define ABIT_UGURU3_ALARMS_START 0x1E -#define ABIT_UGURU3_SETTINGS_START 0x24 -#define ABIT_UGURU3_VALUES_START 0x80 -#define ABIT_UGURU3_BOARD_ID 0x0A -/* uGuru3 sensor bank flags */ /* Alarm if: */ -#define ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE 0x01 /* temp over warn */ -#define ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE 0x02 /* volt over max */ -#define ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE 0x04 /* volt under min */ -#define ABIT_UGURU3_TEMP_HIGH_ALARM_FLAG 0x10 /* temp is over warn */ -#define ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG 0x20 /* volt is over max */ -#define ABIT_UGURU3_VOLT_LOW_ALARM_FLAG 0x40 /* volt is under min */ -#define ABIT_UGURU3_FAN_LOW_ALARM_ENABLE 0x01 /* fan under min */ -#define ABIT_UGURU3_BEEP_ENABLE 0x08 /* beep if alarm */ -#define ABIT_UGURU3_SHUTDOWN_ENABLE 0x80 /* shutdown if alarm */ -/* sensor types */ -#define ABIT_UGURU3_IN_SENSOR 0 -#define ABIT_UGURU3_TEMP_SENSOR 1 -#define ABIT_UGURU3_FAN_SENSOR 2 - -/* - * Timeouts / Retries, if these turn out to need a lot of fiddling we could - * convert them to params. Determined by trial and error. I assume this is - * cpu-speed independent, since the ISA-bus and not the CPU should be the - * bottleneck. - */ -#define ABIT_UGURU3_WAIT_TIMEOUT 250 -/* - * Normally the 0xAC at the end of synchronize() is reported after the - * first read, but sometimes not and we need to poll - */ -#define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT 5 -/* utility macros */ -#define ABIT_UGURU3_NAME "abituguru3" -#define ABIT_UGURU3_DEBUG(format, arg...) \ - if (verbose) \ - printk(KERN_DEBUG ABIT_UGURU3_NAME ": " format , ## arg) - -/* Macros to help calculate the sysfs_names array length */ -#define ABIT_UGURU3_MAX_NO_SENSORS 26 -/* - * sum of strlen +1 of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0, - * in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0, in??_label\0 - */ -#define ABIT_UGURU3_IN_NAMES_LENGTH \ - (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11) -/* - * sum of strlen +1 of: temp??_input\0, temp??_max\0, temp??_crit\0, - * temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0, - * temp??_label\0 - */ -#define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13) -/* - * sum of strlen +1 of: fan??_input\0, fan??_min\0, fan??_alarm\0, - * fan??_alarm_enable\0, fan??_beep\0, fan??_shutdown\0, fan??_label\0 - */ -#define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12) -/* - * Worst case scenario 16 in sensors (longest names_length) and the rest - * temp sensors (second longest names_length). - */ -#define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \ - (ABIT_UGURU3_MAX_NO_SENSORS - 16) * ABIT_UGURU3_TEMP_NAMES_LENGTH) - -/* - * All the macros below are named identical to the openguru2 program - * reverse engineered by Louis Kruger, hence the names might not be 100% - * logical. I could come up with better names, but I prefer keeping the names - * identical so that this driver can be compared with his work more easily. - */ -/* Two i/o-ports are used by uGuru */ -#define ABIT_UGURU3_BASE 0x00E0 -#define ABIT_UGURU3_CMD 0x00 -#define ABIT_UGURU3_DATA 0x04 -#define ABIT_UGURU3_REGION_LENGTH 5 -/* - * The wait_xxx functions return this on success and the last contents - * of the DATA register (0-255) on failure. - */ -#define ABIT_UGURU3_SUCCESS -1 -/* uGuru status flags */ -#define ABIT_UGURU3_STATUS_READY_FOR_READ 0x01 -#define ABIT_UGURU3_STATUS_BUSY 0x02 - - -/* Structures */ -struct abituguru3_sensor_info { - const char *name; - int port; - int type; - int multiplier; - int divisor; - int offset; -}; - -/* Avoid use of flexible array members */ -#define ABIT_UGURU3_MAX_DMI_NAMES 2 - -struct abituguru3_motherboard_info { - u16 id; - const char *dmi_name[ABIT_UGURU3_MAX_DMI_NAMES + 1]; - /* + 1 -> end of sensors indicated by a sensor with name == NULL */ - struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1]; -}; - -/* - * For the Abit uGuru, we need to keep some data in memory. - * The structure is dynamically allocated, at the same time when a new - * abituguru3 device is allocated. - */ -struct abituguru3_data { - struct device *hwmon_dev; /* hwmon registered device */ - struct mutex update_lock; /* protect access to data and uGuru */ - unsigned short addr; /* uguru base address */ - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* - * For convenience the sysfs attr and their names are generated - * automatically. We have max 10 entries per sensor (for in sensors) - */ - struct sensor_device_attribute_2 sysfs_attr[ABIT_UGURU3_MAX_NO_SENSORS - * 10]; - - /* Buffer to store the dynamically generated sysfs names */ - char sysfs_names[ABIT_UGURU3_SYSFS_NAMES_LENGTH]; - - /* Pointer to the sensors info for the detected motherboard */ - const struct abituguru3_sensor_info *sensors; - - /* - * The abituguru3 supports up to 48 sensors, and thus has registers - * sets for 48 sensors, for convienence reasons / simplicity of the - * code we always read and store all registers for all 48 sensors - */ - - /* Alarms for all 48 sensors (1 bit per sensor) */ - u8 alarms[48/8]; - - /* Value of all 48 sensors */ - u8 value[48]; - - /* - * Settings of all 48 sensors, note in and temp sensors (the first 32 - * sensors) have 3 bytes of settings, while fans only have 2 bytes, - * for convenience we use 3 bytes for all sensors - */ - u8 settings[48][3]; -}; - - -/* Constants */ -static const struct abituguru3_motherboard_info abituguru3_motherboards[] = { - { 0x000C, { NULL } /* Unknown, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS FAN", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 35, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x000D, { NULL } /* Abit AW8, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM1", 26, 1, 1, 1, 0 }, - { "PWM2", 27, 1, 1, 1, 0 }, - { "PWM3", 28, 1, 1, 1, 0 }, - { "PWM4", 29, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 35, 2, 60, 1, 0 }, - { "AUX2 Fan", 36, 2, 60, 1, 0 }, - { "AUX3 Fan", 37, 2, 60, 1, 0 }, - { "AUX4 Fan", 38, 2, 60, 1, 0 }, - { "AUX5 Fan", 39, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x000E, { NULL } /* AL-8, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x000F, { NULL } /* Unknown, need DMI string */, { - - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0010, { NULL } /* Abit NI8 SLI GR, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "NB 1.4V", 4, 0, 10, 1, 0 }, - { "SB 1.5V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "SYS", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 35, 2, 60, 1, 0 }, - { "OTES1 Fan", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0011, { "AT8 32X", NULL }, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 20, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 }, - { "NB 1.8V", 4, 0, 10, 1, 0 }, - { "NB 1.8V Dual", 5, 0, 10, 1, 0 }, - { "HTV 1.2", 3, 0, 10, 1, 0 }, - { "PCIE 1.2V", 12, 0, 10, 1, 0 }, - { "NB 1.2V", 13, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "NB", 25, 1, 1, 1, 0 }, - { "System", 26, 1, 1, 1, 0 }, - { "PWM", 27, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 35, 2, 60, 1, 0 }, - { "AUX2 Fan", 36, 2, 60, 1, 0 }, - { "AUX3 Fan", 37, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0012, { NULL } /* Abit AN8 32X, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 20, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "HyperTransport", 3, 0, 10, 1, 0 }, - { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 }, - { "NB", 4, 0, 10, 1, 0 }, - { "SB", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "SYS", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0013, { NULL } /* Abit AW8D, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM1", 26, 1, 1, 1, 0 }, - { "PWM2", 27, 1, 1, 1, 0 }, - { "PWM3", 28, 1, 1, 1, 0 }, - { "PWM4", 29, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 35, 2, 60, 1, 0 }, - { "AUX2 Fan", 36, 2, 60, 1, 0 }, - { "AUX3 Fan", 37, 2, 60, 1, 0 }, - { "AUX4 Fan", 38, 2, 60, 1, 0 }, - { "AUX5 Fan", 39, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0014, { "AB9", "AB9 Pro", NULL }, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 10, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0015, { NULL } /* Unknown, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR", 1, 0, 20, 1, 0 }, - { "DDR VTT", 2, 0, 10, 1, 0 }, - { "HyperTransport", 3, 0, 10, 1, 0 }, - { "CPU VDDA 2.5V", 5, 0, 20, 1, 0 }, - { "NB", 4, 0, 10, 1, 0 }, - { "SB", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "SYS", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 33, 2, 60, 1, 0 }, - { "AUX2 Fan", 35, 2, 60, 1, 0 }, - { "AUX3 Fan", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0016, { "AW9D-MAX", NULL }, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR2", 1, 0, 20, 1, 0 }, - { "DDR2 VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH & PCIE 1.5V", 4, 0, 10, 1, 0 }, - { "MCH 2.5V", 5, 0, 20, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM1", 26, 1, 1, 1, 0 }, - { "PWM2", 27, 1, 1, 1, 0 }, - { "PWM3", 28, 1, 1, 1, 0 }, - { "PWM4", 29, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "NB Fan", 33, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 35, 2, 60, 1, 0 }, - { "AUX2 Fan", 36, 2, 60, 1, 0 }, - { "AUX3 Fan", 37, 2, 60, 1, 0 }, - { "OTES1 Fan", 38, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0017, { NULL } /* Unknown, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR2", 1, 0, 20, 1, 0 }, - { "DDR2 VTT", 2, 0, 10, 1, 0 }, - { "HyperTransport", 3, 0, 10, 1, 0 }, - { "CPU VDDA 2.5V", 6, 0, 20, 1, 0 }, - { "NB 1.8V", 4, 0, 10, 1, 0 }, - { "NB 1.2V ", 13, 0, 10, 1, 0 }, - { "SB 1.2V", 5, 0, 10, 1, 0 }, - { "PCIE 1.2V", 12, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "ATX +3.3V", 10, 0, 20, 1, 0 }, - { "ATX 5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 26, 1, 1, 1, 0 }, - { "PWM", 27, 1, 1, 1, 0 }, - { "CPU FAN", 32, 2, 60, 1, 0 }, - { "SYS FAN", 34, 2, 60, 1, 0 }, - { "AUX1 FAN", 35, 2, 60, 1, 0 }, - { "AUX2 FAN", 36, 2, 60, 1, 0 }, - { "AUX3 FAN", 37, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0018, { "AB9 QuadGT", NULL }, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR2", 1, 0, 20, 1, 0 }, - { "DDR2 VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT", 3, 0, 10, 1, 0 }, - { "MCH 1.25V", 4, 0, 10, 1, 0 }, - { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM Phase1", 26, 1, 1, 1, 0 }, - { "PWM Phase2", 27, 1, 1, 1, 0 }, - { "PWM Phase3", 28, 1, 1, 1, 0 }, - { "PWM Phase4", 29, 1, 1, 1, 0 }, - { "PWM Phase5", 30, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 33, 2, 60, 1, 0 }, - { "AUX2 Fan", 35, 2, 60, 1, 0 }, - { "AUX3 Fan", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0019, { "IN9 32X MAX", NULL }, { - { "CPU Core", 7, 0, 10, 1, 0 }, - { "DDR2", 13, 0, 20, 1, 0 }, - { "DDR2 VTT", 14, 0, 10, 1, 0 }, - { "CPU VTT", 3, 0, 20, 1, 0 }, - { "NB 1.2V", 4, 0, 10, 1, 0 }, - { "SB 1.5V", 6, 0, 10, 1, 0 }, - { "HyperTransport", 5, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 12, 0, 60, 1, 0 }, - { "ATX +12V (4-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "ATX +3.3V", 10, 0, 20, 1, 0 }, - { "ATX 5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM Phase1", 26, 1, 1, 1, 0 }, - { "PWM Phase2", 27, 1, 1, 1, 0 }, - { "PWM Phase3", 28, 1, 1, 1, 0 }, - { "PWM Phase4", 29, 1, 1, 1, 0 }, - { "PWM Phase5", 30, 1, 1, 1, 0 }, - { "CPU FAN", 32, 2, 60, 1, 0 }, - { "SYS FAN", 34, 2, 60, 1, 0 }, - { "AUX1 FAN", 33, 2, 60, 1, 0 }, - { "AUX2 FAN", 35, 2, 60, 1, 0 }, - { "AUX3 FAN", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x001A, { "IP35 Pro", "IP35 Pro XE", NULL }, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR2", 1, 0, 20, 1, 0 }, - { "DDR2 VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT 1.2V", 3, 0, 10, 1, 0 }, - { "MCH 1.25V", 4, 0, 10, 1, 0 }, - { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM", 26, 1, 1, 1, 0 }, - { "PWM Phase2", 27, 1, 1, 1, 0 }, - { "PWM Phase3", 28, 1, 1, 1, 0 }, - { "PWM Phase4", 29, 1, 1, 1, 0 }, - { "PWM Phase5", 30, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 33, 2, 60, 1, 0 }, - { "AUX2 Fan", 35, 2, 60, 1, 0 }, - { "AUX3 Fan", 36, 2, 60, 1, 0 }, - { "AUX4 Fan", 37, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x001B, { NULL } /* Unknown, need DMI string */, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR3", 1, 0, 20, 1, 0 }, - { "DDR3 VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT", 3, 0, 10, 1, 0 }, - { "MCH 1.25V", 4, 0, 10, 1, 0 }, - { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM Phase1", 26, 1, 1, 1, 0 }, - { "PWM Phase2", 27, 1, 1, 1, 0 }, - { "PWM Phase3", 28, 1, 1, 1, 0 }, - { "PWM Phase4", 29, 1, 1, 1, 0 }, - { "PWM Phase5", 30, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 33, 2, 60, 1, 0 }, - { "AUX2 Fan", 35, 2, 60, 1, 0 }, - { "AUX3 Fan", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x001C, { "IX38 QuadGT", NULL }, { - { "CPU Core", 0, 0, 10, 1, 0 }, - { "DDR2", 1, 0, 20, 1, 0 }, - { "DDR2 VTT", 2, 0, 10, 1, 0 }, - { "CPU VTT", 3, 0, 10, 1, 0 }, - { "MCH 1.25V", 4, 0, 10, 1, 0 }, - { "ICHIO 1.5V", 5, 0, 10, 1, 0 }, - { "ICH 1.05V", 6, 0, 10, 1, 0 }, - { "ATX +12V (24-Pin)", 7, 0, 60, 1, 0 }, - { "ATX +12V (8-pin)", 8, 0, 60, 1, 0 }, - { "ATX +5V", 9, 0, 30, 1, 0 }, - { "+3.3V", 10, 0, 20, 1, 0 }, - { "5VSB", 11, 0, 30, 1, 0 }, - { "CPU", 24, 1, 1, 1, 0 }, - { "System", 25, 1, 1, 1, 0 }, - { "PWM Phase1", 26, 1, 1, 1, 0 }, - { "PWM Phase2", 27, 1, 1, 1, 0 }, - { "PWM Phase3", 28, 1, 1, 1, 0 }, - { "PWM Phase4", 29, 1, 1, 1, 0 }, - { "PWM Phase5", 30, 1, 1, 1, 0 }, - { "CPU Fan", 32, 2, 60, 1, 0 }, - { "SYS Fan", 34, 2, 60, 1, 0 }, - { "AUX1 Fan", 33, 2, 60, 1, 0 }, - { "AUX2 Fan", 35, 2, 60, 1, 0 }, - { "AUX3 Fan", 36, 2, 60, 1, 0 }, - { NULL, 0, 0, 0, 0, 0 } } - }, - { 0x0000, { NULL }, { { NULL, 0, 0, 0, 0, 0 } } } -}; - - -/* Insmod parameters */ -static bool force; -module_param(force, bool, 0); -MODULE_PARM_DESC(force, "Set to one to force detection."); -/* Default verbose is 1, since this driver is still in the testing phase */ -static bool verbose = 1; -module_param(verbose, bool, 0644); -MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting"); - -static const char *never_happen = "This should never happen."; -static const char *report_this = - "Please report this to the abituguru3 maintainer (see MAINTAINERS)"; - -/* wait while the uguru is busy (usually after a write) */ -static int abituguru3_wait_while_busy(struct abituguru3_data *data) -{ - u8 x; - int timeout = ABIT_UGURU3_WAIT_TIMEOUT; - - while ((x = inb_p(data->addr + ABIT_UGURU3_DATA)) & - ABIT_UGURU3_STATUS_BUSY) { - timeout--; - if (timeout == 0) - return x; - /* - * sleep a bit before our last try, to give the uGuru3 one - * last chance to respond. - */ - if (timeout == 1) - msleep(1); - } - return ABIT_UGURU3_SUCCESS; -} - -/* wait till uguru is ready to be read */ -static int abituguru3_wait_for_read(struct abituguru3_data *data) -{ - u8 x; - int timeout = ABIT_UGURU3_WAIT_TIMEOUT; - - while (!((x = inb_p(data->addr + ABIT_UGURU3_DATA)) & - ABIT_UGURU3_STATUS_READY_FOR_READ)) { - timeout--; - if (timeout == 0) - return x; - /* - * sleep a bit before our last try, to give the uGuru3 one - * last chance to respond. - */ - if (timeout == 1) - msleep(1); - } - return ABIT_UGURU3_SUCCESS; -} - -/* - * This synchronizes us with the uGuru3's protocol state machine, this - * must be done before each command. - */ -static int abituguru3_synchronize(struct abituguru3_data *data) -{ - int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT; - - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("synchronize timeout during initial busy " - "wait, status: 0x%02x\n", x); - return -EIO; - } - - outb(0x20, data->addr + ABIT_UGURU3_DATA); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, " - "status: 0x%02x\n", x); - return -EIO; - } - - outb(0x10, data->addr + ABIT_UGURU3_CMD); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, " - "status: 0x%02x\n", x); - return -EIO; - } - - outb(0x00, data->addr + ABIT_UGURU3_CMD); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, " - "status: 0x%02x\n", x); - return -EIO; - } - - x = abituguru3_wait_for_read(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, " - "status: 0x%02x\n", x); - return -EIO; - } - - while ((x = inb(data->addr + ABIT_UGURU3_CMD)) != 0xAC) { - timeout--; - if (timeout == 0) { - ABIT_UGURU3_DEBUG("synchronize timeout cmd does not " - "hold 0xAC after synchronize, cmd: 0x%02x\n", - x); - return -EIO; - } - msleep(1); - } - return 0; -} - -/* - * Read count bytes from sensor sensor_addr in bank bank_addr and store the - * result in buf - */ -static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset, - u8 count, u8 *buf) -{ - int i, x; - - x = abituguru3_synchronize(data); - if (x) - return x; - - outb(0x1A, data->addr + ABIT_UGURU3_DATA); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after " - "sending 0x1A, status: 0x%02x\n", (unsigned int)bank, - (unsigned int)offset, x); - return -EIO; - } - - outb(bank, data->addr + ABIT_UGURU3_CMD); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after " - "sending the bank, status: 0x%02x\n", - (unsigned int)bank, (unsigned int)offset, x); - return -EIO; - } - - outb(offset, data->addr + ABIT_UGURU3_CMD); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after " - "sending the offset, status: 0x%02x\n", - (unsigned int)bank, (unsigned int)offset, x); - return -EIO; - } - - outb(count, data->addr + ABIT_UGURU3_CMD); - x = abituguru3_wait_while_busy(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after " - "sending the count, status: 0x%02x\n", - (unsigned int)bank, (unsigned int)offset, x); - return -EIO; - } - - for (i = 0; i < count; i++) { - x = abituguru3_wait_for_read(data); - if (x != ABIT_UGURU3_SUCCESS) { - ABIT_UGURU3_DEBUG("timeout reading byte %d from " - "0x%02x:0x%02x, status: 0x%02x\n", i, - (unsigned int)bank, (unsigned int)offset, x); - break; - } - buf[i] = inb(data->addr + ABIT_UGURU3_CMD); - } - return i; -} - -/* - * Sensor settings are stored 1 byte per offset with the bytes - * placed add consecutive offsets. - */ -static int abituguru3_read_increment_offset(struct abituguru3_data *data, - u8 bank, u8 offset, u8 count, - u8 *buf, int offset_count) -{ - int i, x; - - for (i = 0; i < offset_count; i++) { - x = abituguru3_read(data, bank, offset + i, count, - buf + i * count); - if (x != count) { - if (x < 0) - return x; - return i * count + x; - } - } - - return i * count; -} - -/* - * Following are the sysfs callback functions. These functions expect: - * sensor_device_attribute_2->index: index into the data->sensors array - * sensor_device_attribute_2->nr: register offset, bitmask or NA. - */ -static struct abituguru3_data *abituguru3_update_device(struct device *dev); - -static ssize_t show_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int value; - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru3_data *data = abituguru3_update_device(dev); - const struct abituguru3_sensor_info *sensor; - - if (!data) - return -EIO; - - sensor = &data->sensors[attr->index]; - - /* are we reading a setting, or is this a normal read? */ - if (attr->nr) - value = data->settings[sensor->port][attr->nr]; - else - value = data->value[sensor->port]; - - /* convert the value */ - value = (value * sensor->multiplier) / sensor->divisor + - sensor->offset; - - /* - * alternatively we could update the sensors settings struct for this, - * but then its contents would differ from the windows sw ini files - */ - if (sensor->type == ABIT_UGURU3_TEMP_SENSOR) - value *= 1000; - - return sprintf(buf, "%d\n", value); -} - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int port; - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru3_data *data = abituguru3_update_device(dev); - - if (!data) - return -EIO; - - port = data->sensors[attr->index].port; - - /* - * See if the alarm bit for this sensor is set and if a bitmask is - * given in attr->nr also check if the alarm matches the type of alarm - * we're looking for (for volt it can be either low or high). The type - * is stored in a few readonly bits in the settings of the sensor. - */ - if ((data->alarms[port / 8] & (0x01 << (port % 8))) && - (!attr->nr || (data->settings[port][0] & attr->nr))) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_mask(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru3_data *data = dev_get_drvdata(dev); - - if (data->settings[data->sensors[attr->index].port][0] & attr->nr) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_label(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct abituguru3_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->sensors[attr->index].name); -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", ABIT_UGURU3_NAME); -} - -/* Sysfs attr templates, the real entries are generated automatically. */ -static const -struct sensor_device_attribute_2 abituguru3_sysfs_templ[3][10] = { { - SENSOR_ATTR_2(in%d_input, 0444, show_value, NULL, 0, 0), - SENSOR_ATTR_2(in%d_min, 0444, show_value, NULL, 1, 0), - SENSOR_ATTR_2(in%d_max, 0444, show_value, NULL, 2, 0), - SENSOR_ATTR_2(in%d_min_alarm, 0444, show_alarm, NULL, - ABIT_UGURU3_VOLT_LOW_ALARM_FLAG, 0), - SENSOR_ATTR_2(in%d_max_alarm, 0444, show_alarm, NULL, - ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG, 0), - SENSOR_ATTR_2(in%d_beep, 0444, show_mask, NULL, - ABIT_UGURU3_BEEP_ENABLE, 0), - SENSOR_ATTR_2(in%d_shutdown, 0444, show_mask, NULL, - ABIT_UGURU3_SHUTDOWN_ENABLE, 0), - SENSOR_ATTR_2(in%d_min_alarm_enable, 0444, show_mask, NULL, - ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE, 0), - SENSOR_ATTR_2(in%d_max_alarm_enable, 0444, show_mask, NULL, - ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE, 0), - SENSOR_ATTR_2(in%d_label, 0444, show_label, NULL, 0, 0) - }, { - SENSOR_ATTR_2(temp%d_input, 0444, show_value, NULL, 0, 0), - SENSOR_ATTR_2(temp%d_max, 0444, show_value, NULL, 1, 0), - SENSOR_ATTR_2(temp%d_crit, 0444, show_value, NULL, 2, 0), - SENSOR_ATTR_2(temp%d_alarm, 0444, show_alarm, NULL, 0, 0), - SENSOR_ATTR_2(temp%d_beep, 0444, show_mask, NULL, - ABIT_UGURU3_BEEP_ENABLE, 0), - SENSOR_ATTR_2(temp%d_shutdown, 0444, show_mask, NULL, - ABIT_UGURU3_SHUTDOWN_ENABLE, 0), - SENSOR_ATTR_2(temp%d_alarm_enable, 0444, show_mask, NULL, - ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE, 0), - SENSOR_ATTR_2(temp%d_label, 0444, show_label, NULL, 0, 0) - }, { - SENSOR_ATTR_2(fan%d_input, 0444, show_value, NULL, 0, 0), - SENSOR_ATTR_2(fan%d_min, 0444, show_value, NULL, 1, 0), - SENSOR_ATTR_2(fan%d_alarm, 0444, show_alarm, NULL, 0, 0), - SENSOR_ATTR_2(fan%d_beep, 0444, show_mask, NULL, - ABIT_UGURU3_BEEP_ENABLE, 0), - SENSOR_ATTR_2(fan%d_shutdown, 0444, show_mask, NULL, - ABIT_UGURU3_SHUTDOWN_ENABLE, 0), - SENSOR_ATTR_2(fan%d_alarm_enable, 0444, show_mask, NULL, - ABIT_UGURU3_FAN_LOW_ALARM_ENABLE, 0), - SENSOR_ATTR_2(fan%d_label, 0444, show_label, NULL, 0, 0) -} }; - -static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = { - SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0), -}; - -static int __devinit abituguru3_probe(struct platform_device *pdev) -{ - const int no_sysfs_attr[3] = { 10, 8, 7 }; - int sensor_index[3] = { 0, 1, 1 }; - struct abituguru3_data *data; - int i, j, type, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV; - char *sysfs_filename; - u8 buf[2]; - u16 id; - - data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - /* Read the motherboard ID */ - i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK, ABIT_UGURU3_BOARD_ID, - 2, buf); - if (i != 2) - goto abituguru3_probe_error; - - /* Completely read the uGuru to see if one really is there */ - if (!abituguru3_update_device(&pdev->dev)) - goto abituguru3_probe_error; - - /* lookup the ID in our motherboard table */ - id = ((u16)buf[0] << 8) | (u16)buf[1]; - for (i = 0; abituguru3_motherboards[i].id; i++) - if (abituguru3_motherboards[i].id == id) - break; - if (!abituguru3_motherboards[i].id) { - pr_err("error unknown motherboard ID: %04X. %s\n", - (unsigned int)id, report_this); - goto abituguru3_probe_error; - } - data->sensors = abituguru3_motherboards[i].sensors; - - pr_info("found Abit uGuru3, motherboard ID: %04X\n", (unsigned int)id); - - /* Fill the sysfs attr array */ - sysfs_attr_i = 0; - sysfs_filename = data->sysfs_names; - sysfs_names_free = ABIT_UGURU3_SYSFS_NAMES_LENGTH; - for (i = 0; data->sensors[i].name; i++) { - /* Fail safe check, this should never happen! */ - if (i >= ABIT_UGURU3_MAX_NO_SENSORS) { - pr_err("Fatal error motherboard has more sensors then ABIT_UGURU3_MAX_NO_SENSORS. %s %s\n", - never_happen, report_this); - res = -ENAMETOOLONG; - goto abituguru3_probe_error; - } - type = data->sensors[i].type; - for (j = 0; j < no_sysfs_attr[type]; j++) { - used = snprintf(sysfs_filename, sysfs_names_free, - abituguru3_sysfs_templ[type][j].dev_attr.attr. - name, sensor_index[type]) + 1; - data->sysfs_attr[sysfs_attr_i] = - abituguru3_sysfs_templ[type][j]; - data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name = - sysfs_filename; - data->sysfs_attr[sysfs_attr_i].index = i; - sysfs_filename += used; - sysfs_names_free -= used; - sysfs_attr_i++; - } - sensor_index[type]++; - } - /* Fail safe check, this should never happen! */ - if (sysfs_names_free < 0) { - pr_err("Fatal error ran out of space for sysfs attr names. %s %s\n", - never_happen, report_this); - res = -ENAMETOOLONG; - goto abituguru3_probe_error; - } - - /* Register sysfs hooks */ - for (i = 0; i < sysfs_attr_i; i++) - if (device_create_file(&pdev->dev, - &data->sysfs_attr[i].dev_attr)) - goto abituguru3_probe_error; - for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) - if (device_create_file(&pdev->dev, - &abituguru3_sysfs_attr[i].dev_attr)) - goto abituguru3_probe_error; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - res = PTR_ERR(data->hwmon_dev); - goto abituguru3_probe_error; - } - - return 0; /* success */ - -abituguru3_probe_error: - for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) - device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) - device_remove_file(&pdev->dev, - &abituguru3_sysfs_attr[i].dev_attr); - kfree(data); - return res; -} - -static int __devexit abituguru3_remove(struct platform_device *pdev) -{ - int i; - struct abituguru3_data *data = platform_get_drvdata(pdev); - - platform_set_drvdata(pdev, NULL); - hwmon_device_unregister(data->hwmon_dev); - for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++) - device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) - device_remove_file(&pdev->dev, - &abituguru3_sysfs_attr[i].dev_attr); - kfree(data); - - return 0; -} - -static struct abituguru3_data *abituguru3_update_device(struct device *dev) -{ - int i; - struct abituguru3_data *data = dev_get_drvdata(dev); - - mutex_lock(&data->update_lock); - if (!data->valid || time_after(jiffies, data->last_updated + HZ)) { - /* Clear data->valid while updating */ - data->valid = 0; - /* Read alarms */ - if (abituguru3_read_increment_offset(data, - ABIT_UGURU3_SETTINGS_BANK, - ABIT_UGURU3_ALARMS_START, - 1, data->alarms, 48/8) != (48/8)) - goto LEAVE_UPDATE; - /* Read in and temp sensors (3 byte settings / sensor) */ - for (i = 0; i < 32; i++) { - if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK, - ABIT_UGURU3_VALUES_START + i, - 1, &data->value[i]) != 1) - goto LEAVE_UPDATE; - if (abituguru3_read_increment_offset(data, - ABIT_UGURU3_SETTINGS_BANK, - ABIT_UGURU3_SETTINGS_START + i * 3, - 1, - data->settings[i], 3) != 3) - goto LEAVE_UPDATE; - } - /* Read temp sensors (2 byte settings / sensor) */ - for (i = 0; i < 16; i++) { - if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK, - ABIT_UGURU3_VALUES_START + 32 + i, - 1, &data->value[32 + i]) != 1) - goto LEAVE_UPDATE; - if (abituguru3_read_increment_offset(data, - ABIT_UGURU3_SETTINGS_BANK, - ABIT_UGURU3_SETTINGS_START + 32 * 3 + - i * 2, 1, - data->settings[32 + i], 2) != 2) - goto LEAVE_UPDATE; - } - data->last_updated = jiffies; - data->valid = 1; - } -LEAVE_UPDATE: - mutex_unlock(&data->update_lock); - if (data->valid) - return data; - else - return NULL; -} - -#ifdef CONFIG_PM -static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct abituguru3_data *data = platform_get_drvdata(pdev); - /* - * make sure all communications with the uguru3 are done and no new - * ones are started - */ - mutex_lock(&data->update_lock); - return 0; -} - -static int abituguru3_resume(struct platform_device *pdev) -{ - struct abituguru3_data *data = platform_get_drvdata(pdev); - mutex_unlock(&data->update_lock); - return 0; -} -#else -#define abituguru3_suspend NULL -#define abituguru3_resume NULL -#endif /* CONFIG_PM */ - -static struct platform_driver abituguru3_driver = { - .driver = { - .owner = THIS_MODULE, - .name = ABIT_UGURU3_NAME, - }, - .probe = abituguru3_probe, - .remove = __devexit_p(abituguru3_remove), - .suspend = abituguru3_suspend, - .resume = abituguru3_resume -}; - -static int __init abituguru3_dmi_detect(void) -{ - const char *board_vendor, *board_name; - int i, err = (force) ? 1 : -ENODEV; - const char *const *dmi_name; - size_t sublen; - - board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); - if (!board_vendor || strcmp(board_vendor, "http://www.abit.com.tw/")) - return err; - - board_name = dmi_get_system_info(DMI_BOARD_NAME); - if (!board_name) - return err; - - /* - * At the moment, we don't care about the part of the vendor - * DMI string contained in brackets. Truncate the string at - * the first occurrence of a bracket. Trim any trailing space - * from the substring. - */ - sublen = strcspn(board_name, "("); - while (sublen > 0 && board_name[sublen - 1] == ' ') - sublen--; - - for (i = 0; abituguru3_motherboards[i].id; i++) { - dmi_name = abituguru3_motherboards[i].dmi_name; - for ( ; *dmi_name; dmi_name++) { - if (strlen(*dmi_name) != sublen) - continue; - if (!strncasecmp(board_name, *dmi_name, sublen)) - return 0; - } - } - - /* No match found */ - return 1; -} - -/* - * FIXME: Manual detection should die eventually; we need to collect stable - * DMI model names first before we can rely entirely on CONFIG_DMI. - */ - -static int __init abituguru3_detect(void) -{ - /* - * See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or - * 0x08 at DATA and 0xAC at CMD. Sometimes the uGuru3 will hold 0x05 - * or 0x55 at CMD instead, why is unknown. - */ - u8 data_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_DATA); - u8 cmd_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_CMD); - if (((data_val == 0x00) || (data_val == 0x08)) && - ((cmd_val == 0xAC) || (cmd_val == 0x05) || - (cmd_val == 0x55))) - return 0; - - ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = " - "0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val); - - if (force) { - pr_info("Assuming Abit uGuru3 is present because of \"force\" parameter\n"); - return 0; - } - - /* No uGuru3 found */ - return -ENODEV; -} - -static struct platform_device *abituguru3_pdev; - -static int __init abituguru3_init(void) -{ - struct resource res = { .flags = IORESOURCE_IO }; - int err; - - /* Attempt DMI detection first */ - err = abituguru3_dmi_detect(); - if (err < 0) - return err; - - /* - * Fall back to manual detection if there was no exact - * board name match, or force was specified. - */ - if (err > 0) { - err = abituguru3_detect(); - if (err) - return err; - - pr_warn("this motherboard was not detected using DMI. " - "Please send the output of \"dmidecode\" to the abituguru3 maintainer (see MAINTAINERS)\n"); - } - - err = platform_driver_register(&abituguru3_driver); - if (err) - goto exit; - - abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, - ABIT_UGURU3_BASE); - if (!abituguru3_pdev) { - pr_err("Device allocation failed\n"); - err = -ENOMEM; - goto exit_driver_unregister; - } - - res.start = ABIT_UGURU3_BASE; - res.end = ABIT_UGURU3_BASE + ABIT_UGURU3_REGION_LENGTH - 1; - res.name = ABIT_UGURU3_NAME; - - err = platform_device_add_resources(abituguru3_pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add(abituguru3_pdev); - if (err) { - pr_err("Device addition failed (%d)\n", err); - goto exit_device_put; - } - - return 0; - -exit_device_put: - platform_device_put(abituguru3_pdev); -exit_driver_unregister: - platform_driver_unregister(&abituguru3_driver); -exit: - return err; -} - -static void __exit abituguru3_exit(void) -{ - platform_device_unregister(abituguru3_pdev); - platform_driver_unregister(&abituguru3_driver); -} - -MODULE_AUTHOR("Hans de Goede "); -MODULE_DESCRIPTION("Abit uGuru3 Sensor device"); -MODULE_LICENSE("GPL"); - -module_init(abituguru3_init); -module_exit(abituguru3_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/acpi_power_meter.c b/ANDROID_3.4.5/drivers/hwmon/acpi_power_meter.c deleted file mode 100644 index 9140236a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/acpi_power_meter.c +++ /dev/null @@ -1,1026 +0,0 @@ -/* - * A hwmon driver for ACPI 4.0 power meters - * Copyright (C) 2009 IBM - * - * Author: Darrick J. Wong - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ACPI_POWER_METER_NAME "power_meter" -ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); -#define ACPI_POWER_METER_DEVICE_NAME "Power Meter" -#define ACPI_POWER_METER_CLASS "pwr_meter_resource" - -#define NUM_SENSORS 17 - -#define POWER_METER_CAN_MEASURE (1 << 0) -#define POWER_METER_CAN_TRIP (1 << 1) -#define POWER_METER_CAN_CAP (1 << 2) -#define POWER_METER_CAN_NOTIFY (1 << 3) -#define POWER_METER_IS_BATTERY (1 << 8) -#define UNKNOWN_HYSTERESIS 0xFFFFFFFF - -#define METER_NOTIFY_CONFIG 0x80 -#define METER_NOTIFY_TRIP 0x81 -#define METER_NOTIFY_CAP 0x82 -#define METER_NOTIFY_CAPPING 0x83 -#define METER_NOTIFY_INTERVAL 0x84 - -#define POWER_AVERAGE_NAME "power1_average" -#define POWER_CAP_NAME "power1_cap" -#define POWER_AVG_INTERVAL_NAME "power1_average_interval" -#define POWER_ALARM_NAME "power1_alarm" - -static int cap_in_hardware; -static bool force_cap_on; - -static int can_cap_in_hardware(void) -{ - return force_cap_on || cap_in_hardware; -} - -static const struct acpi_device_id power_meter_ids[] = { - {"ACPI000D", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, power_meter_ids); - -struct acpi_power_meter_capabilities { - u64 flags; - u64 units; - u64 type; - u64 accuracy; - u64 sampling_time; - u64 min_avg_interval; - u64 max_avg_interval; - u64 hysteresis; - u64 configurable_cap; - u64 min_cap; - u64 max_cap; -}; - -struct acpi_power_meter_resource { - struct acpi_device *acpi_dev; - acpi_bus_id name; - struct mutex lock; - struct device *hwmon_dev; - struct acpi_power_meter_capabilities caps; - acpi_string model_number; - acpi_string serial_number; - acpi_string oem_info; - u64 power; - u64 cap; - u64 avg_interval; - int sensors_valid; - unsigned long sensors_last_updated; - struct sensor_device_attribute sensors[NUM_SENSORS]; - int num_sensors; - int trip[2]; - int num_domain_devices; - struct acpi_device **domain_devices; - struct kobject *holders_dir; -}; - -struct ro_sensor_template { - char *label; - ssize_t (*show)(struct device *dev, - struct device_attribute *devattr, - char *buf); - int index; -}; - -struct rw_sensor_template { - char *label; - ssize_t (*show)(struct device *dev, - struct device_attribute *devattr, - char *buf); - ssize_t (*set)(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count); - int index; -}; - -/* Averaging interval */ -static int update_avg_interval(struct acpi_power_meter_resource *resource) -{ - unsigned long long data; - acpi_status status; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GAI", - NULL, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GAI")); - return -ENODEV; - } - - resource->avg_interval = data; - return 0; -} - -static ssize_t show_avg_interval(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - - mutex_lock(&resource->lock); - update_avg_interval(resource); - mutex_unlock(&resource->lock); - - return sprintf(buf, "%llu\n", resource->avg_interval); -} - -static ssize_t set_avg_interval(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; - int res; - unsigned long temp; - unsigned long long data; - acpi_status status; - - res = kstrtoul(buf, 10, &temp); - if (res) - return res; - - if (temp > resource->caps.max_avg_interval || - temp < resource->caps.min_avg_interval) - return -EINVAL; - arg0.integer.value = temp; - - mutex_lock(&resource->lock); - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PAI", - &args, &data); - if (!ACPI_FAILURE(status)) - resource->avg_interval = temp; - mutex_unlock(&resource->lock); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PAI")); - return -EINVAL; - } - - /* _PAI returns 0 on success, nonzero otherwise */ - if (data) - return -EINVAL; - - return count; -} - -/* Cap functions */ -static int update_cap(struct acpi_power_meter_resource *resource) -{ - unsigned long long data; - acpi_status status; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GHL", - NULL, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GHL")); - return -ENODEV; - } - - resource->cap = data; - return 0; -} - -static ssize_t show_cap(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - - mutex_lock(&resource->lock); - update_cap(resource); - mutex_unlock(&resource->lock); - - return sprintf(buf, "%llu\n", resource->cap * 1000); -} - -static ssize_t set_cap(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; - int res; - unsigned long temp; - unsigned long long data; - acpi_status status; - - res = kstrtoul(buf, 10, &temp); - if (res) - return res; - - temp /= 1000; - if (temp > resource->caps.max_cap || temp < resource->caps.min_cap) - return -EINVAL; - arg0.integer.value = temp; - - mutex_lock(&resource->lock); - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_SHL", - &args, &data); - if (!ACPI_FAILURE(status)) - resource->cap = temp; - mutex_unlock(&resource->lock); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SHL")); - return -EINVAL; - } - - /* _SHL returns 0 on success, nonzero otherwise */ - if (data) - return -EINVAL; - - return count; -} - -/* Power meter trip points */ -static int set_acpi_trip(struct acpi_power_meter_resource *resource) -{ - union acpi_object arg_objs[] = { - {ACPI_TYPE_INTEGER}, - {ACPI_TYPE_INTEGER} - }; - struct acpi_object_list args = { 2, arg_objs }; - unsigned long long data; - acpi_status status; - - /* Both trip levels must be set */ - if (resource->trip[0] < 0 || resource->trip[1] < 0) - return 0; - - /* This driver stores min, max; ACPI wants max, min. */ - arg_objs[0].integer.value = resource->trip[1]; - arg_objs[1].integer.value = resource->trip[0]; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PTP", - &args, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTP")); - return -EINVAL; - } - - /* _PTP returns 0 on success, nonzero otherwise */ - if (data) - return -EINVAL; - - return 0; -} - -static ssize_t set_trip(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - int res; - unsigned long temp; - - res = kstrtoul(buf, 10, &temp); - if (res) - return res; - - temp /= 1000; - if (temp < 0) - return -EINVAL; - - mutex_lock(&resource->lock); - resource->trip[attr->index - 7] = temp; - res = set_acpi_trip(resource); - mutex_unlock(&resource->lock); - - if (res) - return res; - - return count; -} - -/* Power meter */ -static int update_meter(struct acpi_power_meter_resource *resource) -{ - unsigned long long data; - acpi_status status; - unsigned long local_jiffies = jiffies; - - if (time_before(local_jiffies, resource->sensors_last_updated + - msecs_to_jiffies(resource->caps.sampling_time)) && - resource->sensors_valid) - return 0; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PMM", - NULL, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMM")); - return -ENODEV; - } - - resource->power = data; - resource->sensors_valid = 1; - resource->sensors_last_updated = jiffies; - return 0; -} - -static ssize_t show_power(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - - mutex_lock(&resource->lock); - update_meter(resource); - mutex_unlock(&resource->lock); - - return sprintf(buf, "%llu\n", resource->power * 1000); -} - -/* Miscellaneous */ -static ssize_t show_str(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - acpi_string val; - - switch (attr->index) { - case 0: - val = resource->model_number; - break; - case 1: - val = resource->serial_number; - break; - case 2: - val = resource->oem_info; - break; - default: - BUG(); - val = ""; - } - - return sprintf(buf, "%s\n", val); -} - -static ssize_t show_val(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - u64 val = 0; - - switch (attr->index) { - case 0: - val = resource->caps.min_avg_interval; - break; - case 1: - val = resource->caps.max_avg_interval; - break; - case 2: - val = resource->caps.min_cap * 1000; - break; - case 3: - val = resource->caps.max_cap * 1000; - break; - case 4: - if (resource->caps.hysteresis == UNKNOWN_HYSTERESIS) - return sprintf(buf, "unknown\n"); - - val = resource->caps.hysteresis * 1000; - break; - case 5: - if (resource->caps.flags & POWER_METER_IS_BATTERY) - val = 1; - else - val = 0; - break; - case 6: - if (resource->power > resource->cap) - val = 1; - else - val = 0; - break; - case 7: - case 8: - if (resource->trip[attr->index - 7] < 0) - return sprintf(buf, "unknown\n"); - - val = resource->trip[attr->index - 7] * 1000; - break; - default: - BUG(); - } - - return sprintf(buf, "%llu\n", val); -} - -static ssize_t show_accuracy(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - unsigned int acc = resource->caps.accuracy; - - return sprintf(buf, "%u.%u%%\n", acc / 1000, acc % 1000); -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME); -} - -/* Sensor descriptions. If you add a sensor, update NUM_SENSORS above! */ -static struct ro_sensor_template meter_ro_attrs[] = { -{POWER_AVERAGE_NAME, show_power, 0}, -{"power1_accuracy", show_accuracy, 0}, -{"power1_average_interval_min", show_val, 0}, -{"power1_average_interval_max", show_val, 1}, -{"power1_is_battery", show_val, 5}, -{NULL, NULL, 0}, -}; - -static struct rw_sensor_template meter_rw_attrs[] = { -{POWER_AVG_INTERVAL_NAME, show_avg_interval, set_avg_interval, 0}, -{NULL, NULL, NULL, 0}, -}; - -static struct ro_sensor_template misc_cap_attrs[] = { -{"power1_cap_min", show_val, 2}, -{"power1_cap_max", show_val, 3}, -{"power1_cap_hyst", show_val, 4}, -{POWER_ALARM_NAME, show_val, 6}, -{NULL, NULL, 0}, -}; - -static struct ro_sensor_template ro_cap_attrs[] = { -{POWER_CAP_NAME, show_cap, 0}, -{NULL, NULL, 0}, -}; - -static struct rw_sensor_template rw_cap_attrs[] = { -{POWER_CAP_NAME, show_cap, set_cap, 0}, -{NULL, NULL, NULL, 0}, -}; - -static struct rw_sensor_template trip_attrs[] = { -{"power1_average_min", show_val, set_trip, 7}, -{"power1_average_max", show_val, set_trip, 8}, -{NULL, NULL, NULL, 0}, -}; - -static struct ro_sensor_template misc_attrs[] = { -{"name", show_name, 0}, -{"power1_model_number", show_str, 0}, -{"power1_oem_info", show_str, 2}, -{"power1_serial_number", show_str, 1}, -{NULL, NULL, 0}, -}; - -/* Read power domain data */ -static void remove_domain_devices(struct acpi_power_meter_resource *resource) -{ - int i; - - if (!resource->num_domain_devices) - return; - - for (i = 0; i < resource->num_domain_devices; i++) { - struct acpi_device *obj = resource->domain_devices[i]; - if (!obj) - continue; - - sysfs_remove_link(resource->holders_dir, - kobject_name(&obj->dev.kobj)); - put_device(&obj->dev); - } - - kfree(resource->domain_devices); - kobject_put(resource->holders_dir); - resource->num_domain_devices = 0; -} - -static int read_domain_devices(struct acpi_power_meter_resource *resource) -{ - int res = 0; - int i; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *pss; - acpi_status status; - - status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMD", NULL, - &buffer); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMD")); - return -ENODEV; - } - - pss = buffer.pointer; - if (!pss || - pss->type != ACPI_TYPE_PACKAGE) { - dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME - "Invalid _PMD data\n"); - res = -EFAULT; - goto end; - } - - if (!pss->package.count) - goto end; - - resource->domain_devices = kzalloc(sizeof(struct acpi_device *) * - pss->package.count, GFP_KERNEL); - if (!resource->domain_devices) { - res = -ENOMEM; - goto end; - } - - resource->holders_dir = kobject_create_and_add("measures", - &resource->acpi_dev->dev.kobj); - if (!resource->holders_dir) { - res = -ENOMEM; - goto exit_free; - } - - resource->num_domain_devices = pss->package.count; - - for (i = 0; i < pss->package.count; i++) { - struct acpi_device *obj; - union acpi_object *element = &(pss->package.elements[i]); - - /* Refuse non-references */ - if (element->type != ACPI_TYPE_LOCAL_REFERENCE) - continue; - - /* Create a symlink to domain objects */ - resource->domain_devices[i] = NULL; - status = acpi_bus_get_device(element->reference.handle, - &resource->domain_devices[i]); - if (ACPI_FAILURE(status)) - continue; - - obj = resource->domain_devices[i]; - get_device(&obj->dev); - - res = sysfs_create_link(resource->holders_dir, &obj->dev.kobj, - kobject_name(&obj->dev.kobj)); - if (res) { - put_device(&obj->dev); - resource->domain_devices[i] = NULL; - } - } - - res = 0; - goto end; - -exit_free: - kfree(resource->domain_devices); -end: - kfree(buffer.pointer); - return res; -} - -/* Registration and deregistration */ -static int register_ro_attrs(struct acpi_power_meter_resource *resource, - struct ro_sensor_template *ro) -{ - struct device *dev = &resource->acpi_dev->dev; - struct sensor_device_attribute *sensors = - &resource->sensors[resource->num_sensors]; - int res = 0; - - while (ro->label) { - sensors->dev_attr.attr.name = ro->label; - sensors->dev_attr.attr.mode = S_IRUGO; - sensors->dev_attr.show = ro->show; - sensors->index = ro->index; - - sysfs_attr_init(&sensors->dev_attr.attr); - res = device_create_file(dev, &sensors->dev_attr); - if (res) { - sensors->dev_attr.attr.name = NULL; - goto error; - } - sensors++; - resource->num_sensors++; - ro++; - } - -error: - return res; -} - -static int register_rw_attrs(struct acpi_power_meter_resource *resource, - struct rw_sensor_template *rw) -{ - struct device *dev = &resource->acpi_dev->dev; - struct sensor_device_attribute *sensors = - &resource->sensors[resource->num_sensors]; - int res = 0; - - while (rw->label) { - sensors->dev_attr.attr.name = rw->label; - sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; - sensors->dev_attr.show = rw->show; - sensors->dev_attr.store = rw->set; - sensors->index = rw->index; - - sysfs_attr_init(&sensors->dev_attr.attr); - res = device_create_file(dev, &sensors->dev_attr); - if (res) { - sensors->dev_attr.attr.name = NULL; - goto error; - } - sensors++; - resource->num_sensors++; - rw++; - } - -error: - return res; -} - -static void remove_attrs(struct acpi_power_meter_resource *resource) -{ - int i; - - for (i = 0; i < resource->num_sensors; i++) { - if (!resource->sensors[i].dev_attr.attr.name) - continue; - device_remove_file(&resource->acpi_dev->dev, - &resource->sensors[i].dev_attr); - } - - remove_domain_devices(resource); - - resource->num_sensors = 0; -} - -static int setup_attrs(struct acpi_power_meter_resource *resource) -{ - int res = 0; - - res = read_domain_devices(resource); - if (res) - return res; - - if (resource->caps.flags & POWER_METER_CAN_MEASURE) { - res = register_ro_attrs(resource, meter_ro_attrs); - if (res) - goto error; - res = register_rw_attrs(resource, meter_rw_attrs); - if (res) - goto error; - } - - if (resource->caps.flags & POWER_METER_CAN_CAP) { - if (!can_cap_in_hardware()) { - dev_err(&resource->acpi_dev->dev, - "Ignoring unsafe software power cap!\n"); - goto skip_unsafe_cap; - } - - if (resource->caps.configurable_cap) { - res = register_rw_attrs(resource, rw_cap_attrs); - if (res) - goto error; - } else { - res = register_ro_attrs(resource, ro_cap_attrs); - if (res) - goto error; - } - res = register_ro_attrs(resource, misc_cap_attrs); - if (res) - goto error; - } -skip_unsafe_cap: - - if (resource->caps.flags & POWER_METER_CAN_TRIP) { - res = register_rw_attrs(resource, trip_attrs); - if (res) - goto error; - } - - res = register_ro_attrs(resource, misc_attrs); - if (res) - goto error; - - return res; -error: - remove_attrs(resource); - return res; -} - -static void free_capabilities(struct acpi_power_meter_resource *resource) -{ - acpi_string *str; - int i; - - str = &resource->model_number; - for (i = 0; i < 3; i++, str++) - kfree(*str); -} - -static int read_capabilities(struct acpi_power_meter_resource *resource) -{ - int res = 0; - int i; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer state = { 0, NULL }; - struct acpi_buffer format = { sizeof("NNNNNNNNNNN"), "NNNNNNNNNNN" }; - union acpi_object *pss; - acpi_string *str; - acpi_status status; - - status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMC", NULL, - &buffer); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMC")); - return -ENODEV; - } - - pss = buffer.pointer; - if (!pss || - pss->type != ACPI_TYPE_PACKAGE || - pss->package.count != 14) { - dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME - "Invalid _PMC data\n"); - res = -EFAULT; - goto end; - } - - /* Grab all the integer data at once */ - state.length = sizeof(struct acpi_power_meter_capabilities); - state.pointer = &resource->caps; - - status = acpi_extract_package(pss, &format, &state); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Invalid data")); - res = -EFAULT; - goto end; - } - - if (resource->caps.units) { - dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME - "Unknown units %llu.\n", - resource->caps.units); - res = -EINVAL; - goto end; - } - - /* Grab the string data */ - str = &resource->model_number; - - for (i = 11; i < 14; i++) { - union acpi_object *element = &(pss->package.elements[i]); - - if (element->type != ACPI_TYPE_STRING) { - res = -EINVAL; - goto error; - } - - *str = kzalloc(sizeof(u8) * (element->string.length + 1), - GFP_KERNEL); - if (!*str) { - res = -ENOMEM; - goto error; - } - - strncpy(*str, element->string.pointer, element->string.length); - str++; - } - - dev_info(&resource->acpi_dev->dev, "Found ACPI power meter.\n"); - goto end; -error: - str = &resource->model_number; - for (i = 0; i < 3; i++, str++) - kfree(*str); -end: - kfree(buffer.pointer); - return res; -} - -/* Handle ACPI event notifications */ -static void acpi_power_meter_notify(struct acpi_device *device, u32 event) -{ - struct acpi_power_meter_resource *resource; - int res; - - if (!device || !acpi_driver_data(device)) - return; - - resource = acpi_driver_data(device); - - mutex_lock(&resource->lock); - switch (event) { - case METER_NOTIFY_CONFIG: - free_capabilities(resource); - res = read_capabilities(resource); - if (res) - break; - - remove_attrs(resource); - setup_attrs(resource); - break; - case METER_NOTIFY_TRIP: - sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME); - update_meter(resource); - break; - case METER_NOTIFY_CAP: - sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME); - update_cap(resource); - break; - case METER_NOTIFY_INTERVAL: - sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME); - update_avg_interval(resource); - break; - case METER_NOTIFY_CAPPING: - sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME); - dev_info(&device->dev, "Capping in progress.\n"); - break; - default: - BUG(); - } - mutex_unlock(&resource->lock); - - acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS, - dev_name(&device->dev), event, 0); -} - -static int acpi_power_meter_add(struct acpi_device *device) -{ - int res; - struct acpi_power_meter_resource *resource; - - if (!device) - return -EINVAL; - - resource = kzalloc(sizeof(struct acpi_power_meter_resource), - GFP_KERNEL); - if (!resource) - return -ENOMEM; - - resource->sensors_valid = 0; - resource->acpi_dev = device; - mutex_init(&resource->lock); - strcpy(acpi_device_name(device), ACPI_POWER_METER_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_POWER_METER_CLASS); - device->driver_data = resource; - - free_capabilities(resource); - res = read_capabilities(resource); - if (res) - goto exit_free; - - resource->trip[0] = resource->trip[1] = -1; - - res = setup_attrs(resource); - if (res) - goto exit_free; - - resource->hwmon_dev = hwmon_device_register(&device->dev); - if (IS_ERR(resource->hwmon_dev)) { - res = PTR_ERR(resource->hwmon_dev); - goto exit_remove; - } - - res = 0; - goto exit; - -exit_remove: - remove_attrs(resource); -exit_free: - kfree(resource); -exit: - return res; -} - -static int acpi_power_meter_remove(struct acpi_device *device, int type) -{ - struct acpi_power_meter_resource *resource; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - resource = acpi_driver_data(device); - hwmon_device_unregister(resource->hwmon_dev); - - free_capabilities(resource); - remove_attrs(resource); - - kfree(resource); - return 0; -} - -static int acpi_power_meter_resume(struct acpi_device *device) -{ - struct acpi_power_meter_resource *resource; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - resource = acpi_driver_data(device); - free_capabilities(resource); - read_capabilities(resource); - - return 0; -} - -static struct acpi_driver acpi_power_meter_driver = { - .name = "power_meter", - .class = ACPI_POWER_METER_CLASS, - .ids = power_meter_ids, - .ops = { - .add = acpi_power_meter_add, - .remove = acpi_power_meter_remove, - .resume = acpi_power_meter_resume, - .notify = acpi_power_meter_notify, - }, -}; - -/* Module init/exit routines */ -static int __init enable_cap_knobs(const struct dmi_system_id *d) -{ - cap_in_hardware = 1; - return 0; -} - -static struct dmi_system_id __initdata pm_dmi_table[] = { - { - enable_cap_knobs, "IBM Active Energy Manager", - { - DMI_MATCH(DMI_SYS_VENDOR, "IBM") - }, - }, - {} -}; - -static int __init acpi_power_meter_init(void) -{ - int result; - - if (acpi_disabled) - return -ENODEV; - - dmi_check_system(pm_dmi_table); - - result = acpi_bus_register_driver(&acpi_power_meter_driver); - if (result < 0) - return -ENODEV; - - return 0; -} - -static void __exit acpi_power_meter_exit(void) -{ - acpi_bus_unregister_driver(&acpi_power_meter_driver); -} - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("ACPI 4.0 power meter driver"); -MODULE_LICENSE("GPL"); - -module_param(force_cap_on, bool, 0644); -MODULE_PARM_DESC(force_cap_on, "Enable power cap even it is unsafe to do so."); - -module_init(acpi_power_meter_init); -module_exit(acpi_power_meter_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/ad7314.c b/ANDROID_3.4.5/drivers/hwmon/ad7314.c deleted file mode 100644 index f85ce70d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ad7314.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * AD7314 digital temperature sensor driver for AD7314, ADT7301 and ADT7302 - * - * Copyright 2010 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - * - * Conversion to hwmon from IIO done by Jonathan Cameron - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * AD7314 power mode - */ -#define AD7314_PD 0x2000 - -/* - * AD7314 temperature masks - */ -#define AD7314_TEMP_SIGN 0x200 -#define AD7314_TEMP_MASK 0x7FE0 -#define AD7314_TEMP_OFFSET 5 - -/* - * ADT7301 and ADT7302 temperature masks - */ -#define ADT7301_TEMP_SIGN 0x2000 -#define ADT7301_TEMP_MASK 0x3FFF - -enum ad7314_variant { - adt7301, - adt7302, - ad7314, -}; - -struct ad7314_data { - struct spi_device *spi_dev; - struct device *hwmon_dev; - u16 rx ____cacheline_aligned; -}; - -static int ad7314_spi_read(struct ad7314_data *chip) -{ - int ret; - - ret = spi_read(chip->spi_dev, (u8 *)&chip->rx, sizeof(chip->rx)); - if (ret < 0) { - dev_err(&chip->spi_dev->dev, "SPI read error\n"); - return ret; - } - - return be16_to_cpu(chip->rx); -} - -static ssize_t ad7314_show_temperature(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ad7314_data *chip = dev_get_drvdata(dev); - s16 data; - int ret; - - ret = ad7314_spi_read(chip); - if (ret < 0) - return ret; - switch (spi_get_device_id(chip->spi_dev)->driver_data) { - case ad7314: - data = (ret & AD7314_TEMP_MASK) >> AD7314_TEMP_OFFSET; - data = (data << 6) >> 6; - - return sprintf(buf, "%d\n", 250 * data); - case adt7301: - case adt7302: - /* - * Documented as a 13 bit twos complement register - * with a sign bit - which is a 14 bit 2's complement - * register. 1lsb - 31.25 milli degrees centigrade - */ - data = ret & ADT7301_TEMP_MASK; - data = (data << 2) >> 2; - - return sprintf(buf, "%d\n", - DIV_ROUND_CLOSEST(data * 3125, 100)); - default: - return -EINVAL; - } -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - ad7314_show_temperature, NULL, 0); - -static struct attribute *ad7314_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ad7314_group = { - .attrs = ad7314_attributes, -}; - -static int __devinit ad7314_probe(struct spi_device *spi_dev) -{ - int ret; - struct ad7314_data *chip; - - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - ret = -ENOMEM; - goto error_ret; - } - dev_set_drvdata(&spi_dev->dev, chip); - - ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group); - if (ret < 0) - goto error_free_chip; - chip->hwmon_dev = hwmon_device_register(&spi_dev->dev); - if (IS_ERR(chip->hwmon_dev)) { - ret = PTR_ERR(chip->hwmon_dev); - goto error_remove_group; - } - chip->spi_dev = spi_dev; - - return 0; -error_remove_group: - sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); -error_free_chip: - kfree(chip); -error_ret: - return ret; -} - -static int __devexit ad7314_remove(struct spi_device *spi_dev) -{ - struct ad7314_data *chip = dev_get_drvdata(&spi_dev->dev); - - hwmon_device_unregister(chip->hwmon_dev); - sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); - kfree(chip); - - return 0; -} - -static const struct spi_device_id ad7314_id[] = { - { "adt7301", adt7301 }, - { "adt7302", adt7302 }, - { "ad7314", ad7314 }, - { } -}; -MODULE_DEVICE_TABLE(spi, ad7314_id); - -static struct spi_driver ad7314_driver = { - .driver = { - .name = "ad7314", - .owner = THIS_MODULE, - }, - .probe = ad7314_probe, - .remove = __devexit_p(ad7314_remove), - .id_table = ad7314_id, -}; - -module_spi_driver(ad7314_driver); - -MODULE_AUTHOR("Sonic Zhang "); -MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital" - " temperature sensor driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ad7414.c b/ANDROID_3.4.5/drivers/hwmon/ad7414.c deleted file mode 100644 index 06d2d60d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ad7414.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * An hwmon driver for the Analog Devices AD7414 - * - * Copyright 2006 Stefan Roese , DENX Software Engineering - * - * Copyright (c) 2008 PIKA Technologies - * Sean MacLennan - * - * Copyright (c) 2008 Spansion Inc. - * Frank Edelhaeuser - * (converted to "new style" I2C driver model, removed checkpatch.pl warnings) - * - * Based on ad7418.c - * Copyright 2006 Tower Technologies, Alessandro Zummo - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* AD7414 registers */ -#define AD7414_REG_TEMP 0x00 -#define AD7414_REG_CONF 0x01 -#define AD7414_REG_T_HIGH 0x02 -#define AD7414_REG_T_LOW 0x03 - -static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW }; - -struct ad7414_data { - struct device *hwmon_dev; - struct mutex lock; /* atomic read data updates */ - char valid; /* !=0 if following fields are valid */ - unsigned long next_update; /* In jiffies */ - s16 temp_input; /* Register values */ - s8 temps[ARRAY_SIZE(AD7414_REG_LIMIT)]; -}; - -/* REG: (0.25C/bit, two's complement) << 6 */ -static inline int ad7414_temp_from_reg(s16 reg) -{ - /* - * use integer division instead of equivalent right shift to - * guarantee arithmetic shift and preserve the sign - */ - return ((int)reg / 64) * 250; -} - -static inline int ad7414_read(struct i2c_client *client, u8 reg) -{ - if (reg == AD7414_REG_TEMP) - return i2c_smbus_read_word_swapped(client, reg); - else - return i2c_smbus_read_byte_data(client, reg); -} - -static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static struct ad7414_data *ad7414_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ad7414_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->lock); - - if (time_after(jiffies, data->next_update) || !data->valid) { - int value, i; - - dev_dbg(&client->dev, "starting ad7414 update\n"); - - value = ad7414_read(client, AD7414_REG_TEMP); - if (value < 0) - dev_dbg(&client->dev, "AD7414_REG_TEMP err %d\n", - value); - else - data->temp_input = value; - - for (i = 0; i < ARRAY_SIZE(AD7414_REG_LIMIT); ++i) { - value = ad7414_read(client, AD7414_REG_LIMIT[i]); - if (value < 0) - dev_dbg(&client->dev, "AD7414 reg %d err %d\n", - AD7414_REG_LIMIT[i], value); - else - data->temps[i] = value; - } - - data->next_update = jiffies + HZ + HZ / 2; - data->valid = 1; - } - - mutex_unlock(&data->lock); - - return data; -} - -static ssize_t show_temp_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ad7414_data *data = ad7414_update_device(dev); - return sprintf(buf, "%d\n", ad7414_temp_from_reg(data->temp_input)); -} -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); - -static ssize_t show_max_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct ad7414_data *data = ad7414_update_device(dev); - return sprintf(buf, "%d\n", data->temps[index] * 1000); -} - -static ssize_t set_max_min(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ad7414_data *data = i2c_get_clientdata(client); - int index = to_sensor_dev_attr(attr)->index; - u8 reg = AD7414_REG_LIMIT[index]; - long temp; - int ret = kstrtol(buf, 10, &temp); - - if (ret < 0) - return ret; - - temp = SENSORS_LIMIT(temp, -40000, 85000); - temp = (temp + (temp < 0 ? -500 : 500)) / 1000; - - mutex_lock(&data->lock); - data->temps[index] = temp; - ad7414_write(client, reg, temp); - mutex_unlock(&data->lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_max_min, set_max_min, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - show_max_min, set_max_min, 1); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct ad7414_data *data = ad7414_update_device(dev); - int value = (data->temp_input >> bitnr) & 1; - return sprintf(buf, "%d\n", value); -} - -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 4); - -static struct attribute *ad7414_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group ad7414_group = { - .attrs = ad7414_attributes, -}; - -static int ad7414_probe(struct i2c_client *client, - const struct i2c_device_id *dev_id) -{ - struct ad7414_data *data; - int conf; - int err; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - err = -EOPNOTSUPP; - goto exit; - } - - data = kzalloc(sizeof(struct ad7414_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); - - dev_info(&client->dev, "chip found\n"); - - /* Make sure the chip is powered up. */ - conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF); - if (conf < 0) - dev_warn(&client->dev, - "ad7414_probe unable to read config register.\n"); - else { - conf &= ~(1 << 7); - i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf); - } - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &ad7414_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &ad7414_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int __devexit ad7414_remove(struct i2c_client *client) -{ - struct ad7414_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ad7414_group); - kfree(data); - return 0; -} - -static const struct i2c_device_id ad7414_id[] = { - { "ad7414", 0 }, - {} -}; -MODULE_DEVICE_TABLE(i2c, ad7414_id); - -static struct i2c_driver ad7414_driver = { - .driver = { - .name = "ad7414", - }, - .probe = ad7414_probe, - .remove = __devexit_p(ad7414_remove), - .id_table = ad7414_id, -}; - -module_i2c_driver(ad7414_driver); - -MODULE_AUTHOR("Stefan Roese , " - "Frank Edelhaeuser "); - -MODULE_DESCRIPTION("AD7414 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ad7418.c b/ANDROID_3.4.5/drivers/hwmon/ad7418.c deleted file mode 100644 index a50a6bef..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ad7418.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * An hwmon driver for the Analog Devices AD7416/17/18 - * Copyright (C) 2006-07 Tower Technologies - * - * Author: Alessandro Zummo - * - * Based on lm75.c - * Copyright (C) 1998-99 Frodo Looijaard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License, - * as published by the Free Software Foundation - version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "lm75.h" - -#define DRV_VERSION "0.4" - -enum chips { ad7416, ad7417, ad7418 }; - -/* AD7418 registers */ -#define AD7418_REG_TEMP_IN 0x00 -#define AD7418_REG_CONF 0x01 -#define AD7418_REG_TEMP_HYST 0x02 -#define AD7418_REG_TEMP_OS 0x03 -#define AD7418_REG_ADC 0x04 -#define AD7418_REG_CONF2 0x05 - -#define AD7418_REG_ADC_CH(x) ((x) << 5) -#define AD7418_CH_TEMP AD7418_REG_ADC_CH(0) - -static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, - AD7418_REG_TEMP_HYST, - AD7418_REG_TEMP_OS }; - -struct ad7418_data { - struct device *hwmon_dev; - struct attribute_group attrs; - enum chips type; - struct mutex lock; - int adc_max; /* number of ADC channels */ - char valid; - unsigned long last_updated; /* In jiffies */ - s16 temp[3]; /* Register values */ - u16 in[4]; -}; - -static int ad7418_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int ad7418_remove(struct i2c_client *client); - -static const struct i2c_device_id ad7418_id[] = { - { "ad7416", ad7416 }, - { "ad7417", ad7417 }, - { "ad7418", ad7418 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad7418_id); - -static struct i2c_driver ad7418_driver = { - .driver = { - .name = "ad7418", - }, - .probe = ad7418_probe, - .remove = ad7418_remove, - .id_table = ad7418_id, -}; - -static void ad7418_init_client(struct i2c_client *client) -{ - struct ad7418_data *data = i2c_get_clientdata(client); - - int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); - if (reg < 0) { - dev_err(&client->dev, "cannot read configuration register\n"); - } else { - dev_info(&client->dev, "configuring for mode 1\n"); - i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe); - - if (data->type == ad7417 || data->type == ad7418) - i2c_smbus_write_byte_data(client, - AD7418_REG_CONF2, 0x00); - } -} - -static struct ad7418_data *ad7418_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ad7418_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - u8 cfg; - int i, ch; - - /* read config register and clear channel bits */ - cfg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); - cfg &= 0x1F; - - i2c_smbus_write_byte_data(client, AD7418_REG_CONF, - cfg | AD7418_CH_TEMP); - udelay(30); - - for (i = 0; i < 3; i++) { - data->temp[i] = - i2c_smbus_read_word_swapped(client, - AD7418_REG_TEMP[i]); - } - - for (i = 0, ch = 4; i < data->adc_max; i++, ch--) { - i2c_smbus_write_byte_data(client, - AD7418_REG_CONF, - cfg | AD7418_REG_ADC_CH(ch)); - - udelay(15); - data->in[data->adc_max - 1 - i] = - i2c_smbus_read_word_swapped(client, - AD7418_REG_ADC); - } - - /* restore old configuration value */ - i2c_smbus_write_word_swapped(client, AD7418_REG_CONF, cfg); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->lock); - - return data; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ad7418_data *data = ad7418_update_device(dev); - return sprintf(buf, "%d\n", - LM75_TEMP_FROM_REG(data->temp[attr->index])); -} - -static ssize_t show_adc(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct ad7418_data *data = ad7418_update_device(dev); - - return sprintf(buf, "%d\n", - ((data->in[attr->index] >> 6) * 2500 + 512) / 1024); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct ad7418_data *data = i2c_get_clientdata(client); - long temp; - int ret = kstrtol(buf, 10, &temp); - - if (ret < 0) - return ret; - - mutex_lock(&data->lock); - data->temp[attr->index] = LM75_TEMP_TO_REG(temp); - i2c_smbus_write_word_swapped(client, - AD7418_REG_TEMP[attr->index], - data->temp[attr->index]); - mutex_unlock(&data->lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, - show_temp, set_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp, set_temp, 2); - -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_adc, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); - -static struct attribute *ad7416_attributes[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - NULL -}; - -static struct attribute *ad7417_attributes[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - NULL -}; - -static struct attribute *ad7418_attributes[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - NULL -}; - -static int ad7418_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct ad7418_data *data; - int err; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) { - err = -EOPNOTSUPP; - goto exit; - } - - data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - - mutex_init(&data->lock); - data->type = id->driver_data; - - switch (data->type) { - case ad7416: - data->adc_max = 0; - data->attrs.attrs = ad7416_attributes; - break; - - case ad7417: - data->adc_max = 4; - data->attrs.attrs = ad7417_attributes; - break; - - case ad7418: - data->adc_max = 1; - data->attrs.attrs = ad7418_attributes; - break; - } - - dev_info(&client->dev, "%s chip found\n", client->name); - - /* Initialize the AD7418 chip */ - ad7418_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &data->attrs); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &data->attrs); -exit_free: - kfree(data); -exit: - return err; -} - -static int ad7418_remove(struct i2c_client *client) -{ - struct ad7418_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->attrs); - kfree(data); - return 0; -} - -module_i2c_driver(ad7418_driver); - -MODULE_AUTHOR("Alessandro Zummo "); -MODULE_DESCRIPTION("AD7416/17/18 driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); diff --git a/ANDROID_3.4.5/drivers/hwmon/adcxx.c b/ANDROID_3.4.5/drivers/hwmon/adcxx.c deleted file mode 100644 index a3d31834..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adcxx.c +++ /dev/null @@ -1,255 +0,0 @@ -/* - * adcxx.c - * - * The adcxx4s is an AD converter family from National Semiconductor (NS). - * - * Copyright (c) 2008 Marc Pignat - * - * The adcxx4s communicates with a host processor via an SPI/Microwire Bus - * interface. This driver supports the whole family of devices with name - * ADCS, where - * * bb is the resolution in number of bits (8, 10, 12) - * * c is the number of channels (1, 2, 4, 8) - * * sss is the maximum conversion speed (021 for 200 kSPS, 051 for 500 kSPS - * and 101 for 1 MSPS) - * - * Complete datasheets are available at National's website here: - * http://www.national.com/ds/DC/ADCS.pdf - * - * Handling of 8, 10 and 12 bits converters are the same, the - * unavailable bits are 0 :) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "adcxx" - -struct adcxx { - struct device *hwmon_dev; - struct mutex lock; - u32 channels; - u32 reference; /* in millivolts */ -}; - -/* sysfs hook function */ -static ssize_t adcxx_read(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adcxx *adc = spi_get_drvdata(spi); - u8 tx_buf[2]; - u8 rx_buf[2]; - int status; - u32 value; - - if (mutex_lock_interruptible(&adc->lock)) - return -ERESTARTSYS; - - if (adc->channels == 1) { - status = spi_read(spi, rx_buf, sizeof(rx_buf)); - } else { - tx_buf[0] = attr->index << 3; /* other bits are don't care */ - status = spi_write_then_read(spi, tx_buf, sizeof(tx_buf), - rx_buf, sizeof(rx_buf)); - } - if (status < 0) { - dev_warn(dev, "SPI synch. transfer failed with status %d\n", - status); - goto out; - } - - value = (rx_buf[0] << 8) + rx_buf[1]; - dev_dbg(dev, "raw value = 0x%x\n", value); - - value = value * adc->reference >> 12; - status = sprintf(buf, "%d\n", value); -out: - mutex_unlock(&adc->lock); - return status; -} - -static ssize_t adcxx_show_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - /* The minimum reference is 0 for this chip family */ - return sprintf(buf, "0\n"); -} - -static ssize_t adcxx_show_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = spi_get_drvdata(spi); - u32 reference; - - if (mutex_lock_interruptible(&adc->lock)) - return -ERESTARTSYS; - - reference = adc->reference; - - mutex_unlock(&adc->lock); - - return sprintf(buf, "%d\n", reference); -} - -static ssize_t adcxx_set_max(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = spi_get_drvdata(spi); - unsigned long value; - - if (kstrtoul(buf, 10, &value)) - return -EINVAL; - - if (mutex_lock_interruptible(&adc->lock)) - return -ERESTARTSYS; - - adc->reference = value; - - mutex_unlock(&adc->lock); - - return count; -} - -static ssize_t adcxx_show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = spi_get_drvdata(spi); - - return sprintf(buf, "adcxx%ds\n", adc->channels); -} - -static struct sensor_device_attribute ad_input[] = { - SENSOR_ATTR(name, S_IRUGO, adcxx_show_name, NULL, 0), - SENSOR_ATTR(in_min, S_IRUGO, adcxx_show_min, NULL, 0), - SENSOR_ATTR(in_max, S_IWUSR | S_IRUGO, adcxx_show_max, - adcxx_set_max, 0), - SENSOR_ATTR(in0_input, S_IRUGO, adcxx_read, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, adcxx_read, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, adcxx_read, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, adcxx_read, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, adcxx_read, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, adcxx_read, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, adcxx_read, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, adcxx_read, NULL, 7), -}; - -/*----------------------------------------------------------------------*/ - -static int __devinit adcxx_probe(struct spi_device *spi) -{ - int channels = spi_get_device_id(spi)->driver_data; - struct adcxx *adc; - int status; - int i; - - adc = kzalloc(sizeof *adc, GFP_KERNEL); - if (!adc) - return -ENOMEM; - - /* set a default value for the reference */ - adc->reference = 3300; - adc->channels = channels; - mutex_init(&adc->lock); - - mutex_lock(&adc->lock); - - spi_set_drvdata(spi, adc); - - for (i = 0; i < 3 + adc->channels; i++) { - status = device_create_file(&spi->dev, &ad_input[i].dev_attr); - if (status) { - dev_err(&spi->dev, "device_create_file failed.\n"); - goto out_err; - } - } - - adc->hwmon_dev = hwmon_device_register(&spi->dev); - if (IS_ERR(adc->hwmon_dev)) { - dev_err(&spi->dev, "hwmon_device_register failed.\n"); - status = PTR_ERR(adc->hwmon_dev); - goto out_err; - } - - mutex_unlock(&adc->lock); - return 0; - -out_err: - for (i--; i >= 0; i--) - device_remove_file(&spi->dev, &ad_input[i].dev_attr); - - spi_set_drvdata(spi, NULL); - mutex_unlock(&adc->lock); - kfree(adc); - return status; -} - -static int __devexit adcxx_remove(struct spi_device *spi) -{ - struct adcxx *adc = spi_get_drvdata(spi); - int i; - - mutex_lock(&adc->lock); - hwmon_device_unregister(adc->hwmon_dev); - for (i = 0; i < 3 + adc->channels; i++) - device_remove_file(&spi->dev, &ad_input[i].dev_attr); - - spi_set_drvdata(spi, NULL); - mutex_unlock(&adc->lock); - kfree(adc); - - return 0; -} - -static const struct spi_device_id adcxx_ids[] = { - { "adcxx1s", 1 }, - { "adcxx2s", 2 }, - { "adcxx4s", 4 }, - { "adcxx8s", 8 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, adcxx_ids); - -static struct spi_driver adcxx_driver = { - .driver = { - .name = "adcxx", - .owner = THIS_MODULE, - }, - .id_table = adcxx_ids, - .probe = adcxx_probe, - .remove = __devexit_p(adcxx_remove), -}; - -module_spi_driver(adcxx_driver); - -MODULE_AUTHOR("Marc Pignat"); -MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adm1021.c b/ANDROID_3.4.5/drivers/hwmon/adm1021.c deleted file mode 100644 index 4394e7e9..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adm1021.c +++ /dev/null @@ -1,486 +0,0 @@ -/* - * adm1021.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998, 1999 Frodo Looijaard and - * Philip Edelbrock - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; - -enum chips { - adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066 }; - -/* adm1021 constants specified below */ - -/* The adm1021 registers */ -/* Read-only */ -/* For nr in 0-1 */ -#define ADM1021_REG_TEMP(nr) (nr) -#define ADM1021_REG_STATUS 0x02 -/* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */ -#define ADM1021_REG_MAN_ID 0xFE -/* ADM1021 = 0x0X, ADM1023 = 0x3X */ -#define ADM1021_REG_DEV_ID 0xFF -/* These use different addresses for reading/writing */ -#define ADM1021_REG_CONFIG_R 0x03 -#define ADM1021_REG_CONFIG_W 0x09 -#define ADM1021_REG_CONV_RATE_R 0x04 -#define ADM1021_REG_CONV_RATE_W 0x0A -/* These are for the ADM1023's additional precision on the remote temp sensor */ -#define ADM1023_REG_REM_TEMP_PREC 0x10 -#define ADM1023_REG_REM_OFFSET 0x11 -#define ADM1023_REG_REM_OFFSET_PREC 0x12 -#define ADM1023_REG_REM_TOS_PREC 0x13 -#define ADM1023_REG_REM_THYST_PREC 0x14 -/* limits */ -/* For nr in 0-1 */ -#define ADM1021_REG_TOS_R(nr) (0x05 + 2 * (nr)) -#define ADM1021_REG_TOS_W(nr) (0x0B + 2 * (nr)) -#define ADM1021_REG_THYST_R(nr) (0x06 + 2 * (nr)) -#define ADM1021_REG_THYST_W(nr) (0x0C + 2 * (nr)) -/* write-only */ -#define ADM1021_REG_ONESHOT 0x0F - -/* Initial values */ - -/* - * Note: Even though I left the low and high limits named os and hyst, - * they don't quite work like a thermostat the way the LM75 does. I.e., - * a lower temp than THYST actually triggers an alarm instead of - * clearing it. Weird, ey? --Phil - */ - -/* Each client has this additional data */ -struct adm1021_data { - struct device *hwmon_dev; - enum chips type; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - char low_power; /* !=0 if device in low power mode */ - unsigned long last_updated; /* In jiffies */ - - int temp_max[2]; /* Register values */ - int temp_min[2]; - int temp[2]; - u8 alarms; - /* Special values for ADM1023 only */ - u8 remote_temp_offset; - u8 remote_temp_offset_prec; -}; - -static int adm1021_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1021_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1021_init_client(struct i2c_client *client); -static int adm1021_remove(struct i2c_client *client); -static struct adm1021_data *adm1021_update_device(struct device *dev); - -/* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ -static bool read_only; - - -static const struct i2c_device_id adm1021_id[] = { - { "adm1021", adm1021 }, - { "adm1023", adm1023 }, - { "max1617", max1617 }, - { "max1617a", max1617a }, - { "thmc10", thmc10 }, - { "lm84", lm84 }, - { "gl523sm", gl523sm }, - { "mc1066", mc1066 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1021_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver adm1021_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1021", - }, - .probe = adm1021_probe, - .remove = adm1021_remove, - .id_table = adm1021_id, - .detect = adm1021_detect, - .address_list = normal_i2c, -}; - -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct adm1021_data *data = adm1021_update_device(dev); - - return sprintf(buf, "%d\n", data->temp[index]); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct adm1021_data *data = adm1021_update_device(dev); - - return sprintf(buf, "%d\n", data->temp_max[index]); -} - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct adm1021_data *data = adm1021_update_device(dev); - - return sprintf(buf, "%d\n", data->temp_min[index]); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1021_data *data = adm1021_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> index) & 1); -} - -static ssize_t show_alarms(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct adm1021_data *data = adm1021_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); - long temp; - int err; - - err = kstrtol(buf, 10, &temp); - if (err) - return err; - temp /= 1000; - - mutex_lock(&data->update_lock); - data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127); - if (!read_only) - i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W(index), - data->temp_max[index]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_temp_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); - long temp; - int err; - - err = kstrtol(buf, 10, &temp); - if (err) - return err; - temp /= 1000; - - mutex_lock(&data->update_lock); - data->temp_min[index] = SENSORS_LIMIT(temp, -128, 127); - if (!read_only) - i2c_smbus_write_byte_data(client, ADM1021_REG_THYST_W(index), - data->temp_min[index]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_low_power(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct adm1021_data *data = adm1021_update_device(dev); - return sprintf(buf, "%d\n", data->low_power); -} - -static ssize_t set_low_power(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); - char low_power; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - low_power = val != 0; - - mutex_lock(&data->update_lock); - if (low_power != data->low_power) { - int config = i2c_smbus_read_byte_data( - client, ADM1021_REG_CONFIG_R); - data->low_power = low_power; - i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, - (config & 0xBF) | (low_power << 6)); - } - mutex_unlock(&data->update_lock); - - return count; -} - - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static DEVICE_ATTR(low_power, S_IWUSR | S_IRUGO, show_low_power, set_low_power); - -static struct attribute *adm1021_attributes[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_low_power.attr, - NULL -}; - -static const struct attribute_group adm1021_group = { - .attrs = adm1021_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1021_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - const char *type_name; - int conv_rate, status, config, man_id, dev_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - pr_debug("adm1021: detect failed, " - "smbus byte data not supported!\n"); - return -ENODEV; - } - - status = i2c_smbus_read_byte_data(client, ADM1021_REG_STATUS); - conv_rate = i2c_smbus_read_byte_data(client, - ADM1021_REG_CONV_RATE_R); - config = i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R); - - /* Check unused bits */ - if ((status & 0x03) || (config & 0x3F) || (conv_rate & 0xF8)) { - pr_debug("adm1021: detect failed, chip not detected!\n"); - return -ENODEV; - } - - /* Determine the chip type. */ - man_id = i2c_smbus_read_byte_data(client, ADM1021_REG_MAN_ID); - dev_id = i2c_smbus_read_byte_data(client, ADM1021_REG_DEV_ID); - - if (man_id == 0x4d && dev_id == 0x01) - type_name = "max1617a"; - else if (man_id == 0x41) { - if ((dev_id & 0xF0) == 0x30) - type_name = "adm1023"; - else - type_name = "adm1021"; - } else if (man_id == 0x49) - type_name = "thmc10"; - else if (man_id == 0x23) - type_name = "gl523sm"; - else if (man_id == 0x54) - type_name = "mc1066"; - /* LM84 Mfr ID in a different place, and it has more unused bits */ - else if (conv_rate == 0x00 - && (config & 0x7F) == 0x00 - && (status & 0xAB) == 0x00) - type_name = "lm84"; - else - type_name = "max1617"; - - pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n", - type_name, i2c_adapter_id(adapter), client->addr); - strlcpy(info->type, type_name, I2C_NAME_SIZE); - - return 0; -} - -static int adm1021_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1021_data *data; - int err; - - data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL); - if (!data) { - pr_debug("adm1021: detect failed, kzalloc failed!\n"); - err = -ENOMEM; - goto error0; - } - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - mutex_init(&data->update_lock); - - /* Initialize the ADM1021 chip */ - if (data->type != lm84 && !read_only) - adm1021_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1021_group); - if (err) - goto error1; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error3; - } - - return 0; - -error3: - sysfs_remove_group(&client->dev.kobj, &adm1021_group); -error1: - kfree(data); -error0: - return err; -} - -static void adm1021_init_client(struct i2c_client *client) -{ - /* Enable ADC and disable suspend mode */ - i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, - i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF); - /* Set Conversion rate to 1/sec (this can be tinkered with) */ - i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); -} - -static int adm1021_remove(struct i2c_client *client) -{ - struct adm1021_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1021_group); - - kfree(data); - return 0; -} - -static struct adm1021_data *adm1021_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1021_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - - dev_dbg(&client->dev, "Starting adm1021 update\n"); - - for (i = 0; i < 2; i++) { - data->temp[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_TEMP(i)); - data->temp_max[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_TOS_R(i)); - data->temp_min[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_THYST_R(i)); - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM1021_REG_STATUS) & 0x7c; - if (data->type == adm1023) { - /* - * The ADM1023 provides 3 extra bits of precision for - * the remote sensor in extra registers. - */ - data->temp[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_TEMP_PREC) >> 5); - data->temp_max[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_TOS_PREC) >> 5); - data->temp_min[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_THYST_PREC) >> 5); - data->remote_temp_offset = - i2c_smbus_read_byte_data(client, - ADM1023_REG_REM_OFFSET); - data->remote_temp_offset_prec = - i2c_smbus_read_byte_data(client, - ADM1023_REG_REM_OFFSET_PREC); - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(adm1021_driver); - -MODULE_AUTHOR("Frodo Looijaard and " - "Philip Edelbrock "); -MODULE_DESCRIPTION("adm1021 driver"); -MODULE_LICENSE("GPL"); - -module_param(read_only, bool, 0); -MODULE_PARM_DESC(read_only, "Don't set any values, read only mode"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adm1025.c b/ANDROID_3.4.5/drivers/hwmon/adm1025.c deleted file mode 100644 index b8557f98..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adm1025.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * adm1025.c - * - * Copyright (C) 2000 Chen-Yuan Wu - * Copyright (C) 2003-2009 Jean Delvare - * - * The ADM1025 is a sensor chip made by Analog Devices. It reports up to 6 - * voltages (including its own power source) and up to two temperatures - * (its own plus up to one external one). Voltages are scaled internally - * (which is not the common way) with ratios such that the nominal value - * of each voltage correspond to a register value of 192 (which means a - * resolution of about 0.5% of the nominal value). Temperature values are - * reported with a 1 deg resolution and a 3 deg accuracy. Complete - * datasheet can be obtained from Analog's website at: - * http://www.onsemi.com/PowerSolutions/product.do?id=ADM1025 - * - * This driver also supports the ADM1025A, which differs from the ADM1025 - * only in that it has "open-drain VID inputs while the ADM1025 has - * on-chip 100k pull-ups on the VID inputs". It doesn't make any - * difference for us. - * - * This driver also supports the NE1619, a sensor chip made by Philips. - * That chip is similar to the ADM1025A, with a few differences. The only - * difference that matters to us is that the NE1619 has only two possible - * addresses while the ADM1025A has a third one. Complete datasheet can be - * obtained from Philips's website at: - * http://www.semiconductors.philips.com/pip/NE1619DS.html - * - * Since the ADM1025 was the first chipset supported by this driver, most - * comments will refer to this chipset, but are actually general and - * concern all supported chipsets, unless mentioned otherwise. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - * ADM1025 and ADM1025A have three possible addresses: 0x2c, 0x2d and 0x2e. - * NE1619 has two possible addresses: 0x2c and 0x2d. - */ - -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -enum chips { adm1025, ne1619 }; - -/* - * The ADM1025 registers - */ - -#define ADM1025_REG_MAN_ID 0x3E -#define ADM1025_REG_CHIP_ID 0x3F -#define ADM1025_REG_CONFIG 0x40 -#define ADM1025_REG_STATUS1 0x41 -#define ADM1025_REG_STATUS2 0x42 -#define ADM1025_REG_IN(nr) (0x20 + (nr)) -#define ADM1025_REG_IN_MAX(nr) (0x2B + (nr) * 2) -#define ADM1025_REG_IN_MIN(nr) (0x2C + (nr) * 2) -#define ADM1025_REG_TEMP(nr) (0x26 + (nr)) -#define ADM1025_REG_TEMP_HIGH(nr) (0x37 + (nr) * 2) -#define ADM1025_REG_TEMP_LOW(nr) (0x38 + (nr) * 2) -#define ADM1025_REG_VID 0x47 -#define ADM1025_REG_VID4 0x49 - -/* - * Conversions and various macros - * The ADM1025 uses signed 8-bit values for temperatures. - */ - -static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; - -#define IN_FROM_REG(reg, scale) (((reg) * (scale) + 96) / 192) -#define IN_TO_REG(val, scale) ((val) <= 0 ? 0 : \ - (val) * 192 >= (scale) * 255 ? 255 : \ - ((val) * 192 + (scale) / 2) / (scale)) - -#define TEMP_FROM_REG(reg) ((reg) * 1000) -#define TEMP_TO_REG(val) ((val) <= -127500 ? -128 : \ - (val) >= 126500 ? 127 : \ - (((val) < 0 ? (val) - 500 : \ - (val) + 500) / 1000)) - -/* - * Functions declaration - */ - -static int adm1025_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1025_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1025_init_client(struct i2c_client *client); -static int adm1025_remove(struct i2c_client *client); -static struct adm1025_data *adm1025_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id adm1025_id[] = { - { "adm1025", adm1025 }, - { "ne1619", ne1619 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1025_id); - -static struct i2c_driver adm1025_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1025", - }, - .probe = adm1025_probe, - .remove = adm1025_remove, - .id_table = adm1025_id, - .detect = adm1025_detect, - .address_list = normal_i2c, -}; - -/* - * Client data (each client gets its own) - */ - -struct adm1025_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - u8 in[6]; /* register value */ - u8 in_max[6]; /* register value */ - u8 in_min[6]; /* register value */ - s8 temp[2]; /* register value */ - s8 temp_min[2]; /* register value */ - s8 temp_max[2]; /* register value */ - u16 alarms; /* register values, combined */ - u8 vid; /* register values, combined */ - u8 vrm; -}; - -/* - * Sysfs stuff - */ - -static ssize_t -show_in(struct device *dev, struct device_attribute *attr, char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in[index], - in_scale[index])); -} - -static ssize_t -show_in_min(struct device *dev, struct device_attribute *attr, char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[index], - in_scale[index])); -} - -static ssize_t -show_in_max(struct device *dev, struct device_attribute *attr, char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[index], - in_scale[index])); -} - -static ssize_t -show_temp(struct device *dev, struct device_attribute *attr, char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[index])); -} - -static ssize_t -show_temp_min(struct device *dev, struct device_attribute *attr, char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[index])); -} - -static ssize_t -show_temp_max(struct device *dev, struct device_attribute *attr, char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index])); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[index] = IN_TO_REG(val, in_scale[index]); - i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MIN(index), - data->in_min[index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[index] = IN_TO_REG(val, in_scale[index]); - i2c_smbus_write_byte_data(client, ADM1025_REG_IN_MAX(index), - data->in_max[index]); - mutex_unlock(&data->update_lock); - return count; -} - -#define set_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \ - show_in_max, set_in_max, offset) -set_in(0); -set_in(1); -set_in(2); -set_in(3); -set_in(4); -set_in(5); - -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[index] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_LOW(index), - data->temp_min[index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[index] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, ADM1025_REG_TEMP_HIGH(index), - data->temp_max[index]); - mutex_unlock(&data->update_lock); - return count; -} - -#define set_temp(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \ - show_temp_min, set_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \ - show_temp_max, set_temp_max, offset - 1) -set_temp(1); -set_temp(2); - -static ssize_t -show_alarms(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t -show_alarm(struct device *dev, struct device_attribute *attr, char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14); - -static ssize_t -show_vid(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct adm1025_data *data = adm1025_update_device(dev); - return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -static ssize_t -show_vrm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct adm1025_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", data->vrm); -} -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct adm1025_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); - -/* - * Real code - */ - -static struct attribute *adm1025_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - NULL -}; - -static const struct attribute_group adm1025_group = { - .attrs = adm1025_attributes, -}; - -static struct attribute *adm1025_attributes_in4[] = { - &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 -}; - -static const struct attribute_group adm1025_group_in4 = { - .attrs = adm1025_attributes_in4, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1025_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - const char *name; - u8 man_id, chip_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Check for unused bits */ - if ((i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG) & 0x80) - || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS1) & 0xC0) - || (i2c_smbus_read_byte_data(client, ADM1025_REG_STATUS2) & 0xBC)) { - dev_dbg(&adapter->dev, "ADM1025 detection failed at 0x%02x\n", - client->addr); - return -ENODEV; - } - - /* Identification */ - chip_id = i2c_smbus_read_byte_data(client, ADM1025_REG_CHIP_ID); - if ((chip_id & 0xF0) != 0x20) - return -ENODEV; - - man_id = i2c_smbus_read_byte_data(client, ADM1025_REG_MAN_ID); - if (man_id == 0x41) - name = "adm1025"; - else if (man_id == 0xA1 && client->addr != 0x2E) - name = "ne1619"; - else - return -ENODEV; - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int adm1025_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1025_data *data; - int err; - u8 config; - - data = kzalloc(sizeof(struct adm1025_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the ADM1025 chip */ - adm1025_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1025_group); - if (err) - goto exit_free; - - /* Pin 11 is either in4 (+12V) or VID4 */ - config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); - if (!(config & 0x20)) { - err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &adm1025_group); - sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); -exit_free: - kfree(data); -exit: - return err; -} - -static void adm1025_init_client(struct i2c_client *client) -{ - u8 reg; - struct adm1025_data *data = i2c_get_clientdata(client); - int i; - - data->vrm = vid_which_vrm(); - - /* - * Set high limits - * Usually we avoid setting limits on driver init, but it happens - * that the ADM1025 comes with stupid default limits (all registers - * set to 0). In case the chip has not gone through any limit - * setting yet, we better set the high limits to the max so that - * no alarm triggers. - */ - for (i = 0; i < 6; i++) { - reg = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN_MAX(i)); - if (reg == 0) - i2c_smbus_write_byte_data(client, - ADM1025_REG_IN_MAX(i), - 0xFF); - } - for (i = 0; i < 2; i++) { - reg = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP_HIGH(i)); - if (reg == 0) - i2c_smbus_write_byte_data(client, - ADM1025_REG_TEMP_HIGH(i), - 0x7F); - } - - /* - * Start the conversions - */ - reg = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); - if (!(reg & 0x01)) - i2c_smbus_write_byte_data(client, ADM1025_REG_CONFIG, - (reg&0x7E)|0x01); -} - -static int adm1025_remove(struct i2c_client *client) -{ - struct adm1025_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1025_group); - sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); - - kfree(data); - return 0; -} - -static struct adm1025_data *adm1025_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - int i; - - dev_dbg(&client->dev, "Updating data.\n"); - for (i = 0; i < 6; i++) { - data->in[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN(i)); - data->in_min[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN_MIN(i)); - data->in_max[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN_MAX(i)); - } - for (i = 0; i < 2; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP(i)); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP_LOW(i)); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP_HIGH(i)); - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM1025_REG_STATUS1) - | (i2c_smbus_read_byte_data(client, - ADM1025_REG_STATUS2) << 8); - data->vid = (i2c_smbus_read_byte_data(client, - ADM1025_REG_VID) & 0x0f) - | ((i2c_smbus_read_byte_data(client, - ADM1025_REG_VID4) & 0x01) << 4); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(adm1025_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("ADM1025 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adm1026.c b/ANDROID_3.4.5/drivers/hwmon/adm1026.c deleted file mode 100644 index 1003219b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adm1026.c +++ /dev/null @@ -1,1904 +0,0 @@ -/* - * adm1026.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2002, 2003 Philip Pokorny - * Copyright (C) 2004 Justin Thiessen - * - * Chip details at: - * - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -static int gpio_input[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; -static int gpio_output[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; -static int gpio_inverted[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; -static int gpio_normal[17] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1 }; -static int gpio_fan[8] = { -1, -1, -1, -1, -1, -1, -1, -1 }; -module_param_array(gpio_input, int, NULL, 0); -MODULE_PARM_DESC(gpio_input, "List of GPIO pins (0-16) to program as inputs"); -module_param_array(gpio_output, int, NULL, 0); -MODULE_PARM_DESC(gpio_output, "List of GPIO pins (0-16) to program as " - "outputs"); -module_param_array(gpio_inverted, int, NULL, 0); -MODULE_PARM_DESC(gpio_inverted, "List of GPIO pins (0-16) to program as " - "inverted"); -module_param_array(gpio_normal, int, NULL, 0); -MODULE_PARM_DESC(gpio_normal, "List of GPIO pins (0-16) to program as " - "normal/non-inverted"); -module_param_array(gpio_fan, int, NULL, 0); -MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs"); - -/* Many ADM1026 constants specified below */ - -/* The ADM1026 registers */ -#define ADM1026_REG_CONFIG1 0x00 -#define CFG1_MONITOR 0x01 -#define CFG1_INT_ENABLE 0x02 -#define CFG1_INT_CLEAR 0x04 -#define CFG1_AIN8_9 0x08 -#define CFG1_THERM_HOT 0x10 -#define CFG1_DAC_AFC 0x20 -#define CFG1_PWM_AFC 0x40 -#define CFG1_RESET 0x80 - -#define ADM1026_REG_CONFIG2 0x01 -/* CONFIG2 controls FAN0/GPIO0 through FAN7/GPIO7 */ - -#define ADM1026_REG_CONFIG3 0x07 -#define CFG3_GPIO16_ENABLE 0x01 -#define CFG3_CI_CLEAR 0x02 -#define CFG3_VREF_250 0x04 -#define CFG3_GPIO16_DIR 0x40 -#define CFG3_GPIO16_POL 0x80 - -#define ADM1026_REG_E2CONFIG 0x13 -#define E2CFG_READ 0x01 -#define E2CFG_WRITE 0x02 -#define E2CFG_ERASE 0x04 -#define E2CFG_ROM 0x08 -#define E2CFG_CLK_EXT 0x80 - -/* - * There are 10 general analog inputs and 7 dedicated inputs - * They are: - * 0 - 9 = AIN0 - AIN9 - * 10 = Vbat - * 11 = 3.3V Standby - * 12 = 3.3V Main - * 13 = +5V - * 14 = Vccp (CPU core voltage) - * 15 = +12V - * 16 = -12V - */ -static u16 ADM1026_REG_IN[] = { - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, - 0x36, 0x37, 0x27, 0x29, 0x26, 0x2a, - 0x2b, 0x2c, 0x2d, 0x2e, 0x2f - }; -static u16 ADM1026_REG_IN_MIN[] = { - 0x58, 0x59, 0x5a, 0x5b, 0x5c, 0x5d, - 0x5e, 0x5f, 0x6d, 0x49, 0x6b, 0x4a, - 0x4b, 0x4c, 0x4d, 0x4e, 0x4f - }; -static u16 ADM1026_REG_IN_MAX[] = { - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, - 0x56, 0x57, 0x6c, 0x41, 0x6a, 0x42, - 0x43, 0x44, 0x45, 0x46, 0x47 - }; - -/* - * Temperatures are: - * 0 - Internal - * 1 - External 1 - * 2 - External 2 - */ -static u16 ADM1026_REG_TEMP[] = { 0x1f, 0x28, 0x29 }; -static u16 ADM1026_REG_TEMP_MIN[] = { 0x69, 0x48, 0x49 }; -static u16 ADM1026_REG_TEMP_MAX[] = { 0x68, 0x40, 0x41 }; -static u16 ADM1026_REG_TEMP_TMIN[] = { 0x10, 0x11, 0x12 }; -static u16 ADM1026_REG_TEMP_THERM[] = { 0x0d, 0x0e, 0x0f }; -static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f }; - -#define ADM1026_REG_FAN(nr) (0x38 + (nr)) -#define ADM1026_REG_FAN_MIN(nr) (0x60 + (nr)) -#define ADM1026_REG_FAN_DIV_0_3 0x02 -#define ADM1026_REG_FAN_DIV_4_7 0x03 - -#define ADM1026_REG_DAC 0x04 -#define ADM1026_REG_PWM 0x05 - -#define ADM1026_REG_GPIO_CFG_0_3 0x08 -#define ADM1026_REG_GPIO_CFG_4_7 0x09 -#define ADM1026_REG_GPIO_CFG_8_11 0x0a -#define ADM1026_REG_GPIO_CFG_12_15 0x0b -/* CFG_16 in REG_CFG3 */ -#define ADM1026_REG_GPIO_STATUS_0_7 0x24 -#define ADM1026_REG_GPIO_STATUS_8_15 0x25 -/* STATUS_16 in REG_STATUS4 */ -#define ADM1026_REG_GPIO_MASK_0_7 0x1c -#define ADM1026_REG_GPIO_MASK_8_15 0x1d -/* MASK_16 in REG_MASK4 */ - -#define ADM1026_REG_COMPANY 0x16 -#define ADM1026_REG_VERSTEP 0x17 -/* These are the recognized values for the above regs */ -#define ADM1026_COMPANY_ANALOG_DEV 0x41 -#define ADM1026_VERSTEP_GENERIC 0x40 -#define ADM1026_VERSTEP_ADM1026 0x44 - -#define ADM1026_REG_MASK1 0x18 -#define ADM1026_REG_MASK2 0x19 -#define ADM1026_REG_MASK3 0x1a -#define ADM1026_REG_MASK4 0x1b - -#define ADM1026_REG_STATUS1 0x20 -#define ADM1026_REG_STATUS2 0x21 -#define ADM1026_REG_STATUS3 0x22 -#define ADM1026_REG_STATUS4 0x23 - -#define ADM1026_FAN_ACTIVATION_TEMP_HYST -6 -#define ADM1026_FAN_CONTROL_TEMP_RANGE 20 -#define ADM1026_PWM_MAX 255 - -/* - * Conversions. Rounding and limit checking is only done on the TO_REG - * variants. Note that you should be a bit careful with which arguments - * these macros are called: arguments may be evaluated more than once. - */ - -/* - * IN are scaled according to built-in resistors. These are the - * voltages corresponding to 3/4 of full scale (192 or 0xc0) - * NOTE: The -12V input needs an additional factor to account - * for the Vref pullup resistor. - * NEG12_OFFSET = SCALE * Vref / V-192 - Vref - * = 13875 * 2.50 / 1.875 - 2500 - * = 16000 - * - * The values in this table are based on Table II, page 15 of the - * datasheet. - */ -static int adm1026_scaling[] = { /* .001 Volts */ - 2250, 2250, 2250, 2250, 2250, 2250, - 1875, 1875, 1875, 1875, 3000, 3330, - 3330, 4995, 2250, 12000, 13875 - }; -#define NEG12_OFFSET 16000 -#define SCALE(val, from, to) (((val)*(to) + ((from)/2))/(from)) -#define INS_TO_REG(n, val) (SENSORS_LIMIT(SCALE(val, adm1026_scaling[n], 192),\ - 0, 255)) -#define INS_FROM_REG(n, val) (SCALE(val, 192, adm1026_scaling[n])) - -/* - * FAN speed is measured using 22.5kHz clock and counts for 2 pulses - * and we assume a 2 pulse-per-rev fan tach signal - * 22500 kHz * 60 (sec/min) * 2 (pulse) / 2 (pulse/rev) == 1350000 - */ -#define FAN_TO_REG(val, div) ((val) <= 0 ? 0xff : \ - SENSORS_LIMIT(1350000 / ((val) * (div)), \ - 1, 254)) -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 0xff ? 0 : \ - 1350000 / ((val) * (div))) -#define DIV_FROM_REG(val) (1 << (val)) -#define DIV_TO_REG(val) ((val) >= 8 ? 3 : (val) >= 4 ? 2 : (val) >= 2 ? 1 : 0) - -/* Temperature is reported in 1 degC increments */ -#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \ - / 1000, -127, 127)) -#define TEMP_FROM_REG(val) ((val) * 1000) -#define OFFSET_TO_REG(val) (SENSORS_LIMIT(((val) + ((val) < 0 ? -500 : 500)) \ - / 1000, -127, 127)) -#define OFFSET_FROM_REG(val) ((val) * 1000) - -#define PWM_TO_REG(val) (SENSORS_LIMIT(val, 0, 255)) -#define PWM_FROM_REG(val) (val) - -#define PWM_MIN_TO_REG(val) ((val) & 0xf0) -#define PWM_MIN_FROM_REG(val) (((val) & 0xf0) + ((val) >> 4)) - -/* - * Analog output is a voltage, and scaled to millivolts. The datasheet - * indicates that the DAC could be used to drive the fans, but in our - * example board (Arima HDAMA) it isn't connected to the fans at all. - */ -#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val) * 255) + 500) / 2500), 0, 255)) -#define DAC_FROM_REG(val) (((val) * 2500) / 255) - -/* - * Chip sampling rates - * - * Some sensors are not updated more frequently than once per second - * so it doesn't make sense to read them more often than that. - * We cache the results and return the saved data if the driver - * is called again before a second has elapsed. - * - * Also, there is significant configuration data for this chip - * So, we keep the config data up to date in the cache - * when it is written and only sample it once every 5 *minutes* - */ -#define ADM1026_DATA_INTERVAL (1 * HZ) -#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ) - -/* - * We allow for multiple chips in a single system. - * - * For each registered ADM1026, we need to keep state information - * at client->data. The adm1026_data structure is dynamically - * allocated, when a new client structure is allocated. - */ - -struct pwm_data { - u8 pwm; - u8 enable; - u8 auto_pwm_min; -}; - -struct adm1026_data { - struct device *hwmon_dev; - - struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ - unsigned long last_reading; /* In jiffies */ - unsigned long last_config; /* In jiffies */ - - u8 in[17]; /* Register value */ - u8 in_max[17]; /* Register value */ - u8 in_min[17]; /* Register value */ - s8 temp[3]; /* Register value */ - s8 temp_min[3]; /* Register value */ - s8 temp_max[3]; /* Register value */ - s8 temp_tmin[3]; /* Register value */ - s8 temp_crit[3]; /* Register value */ - s8 temp_offset[3]; /* Register value */ - u8 fan[8]; /* Register value */ - u8 fan_min[8]; /* Register value */ - u8 fan_div[8]; /* Decoded value */ - struct pwm_data pwm1; /* Pwm control values */ - u8 vrm; /* VRM version */ - u8 analog_out; /* Register value (DAC) */ - long alarms; /* Register encoding, combined */ - long alarm_mask; /* Register encoding, combined */ - long gpio; /* Register encoding, combined */ - long gpio_mask; /* Register encoding, combined */ - u8 gpio_config[17]; /* Decoded value */ - u8 config1; /* Register value */ - u8 config2; /* Register value */ - u8 config3; /* Register value */ -}; - -static int adm1026_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1026_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adm1026_remove(struct i2c_client *client); -static int adm1026_read_value(struct i2c_client *client, u8 reg); -static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); -static void adm1026_print_gpio(struct i2c_client *client); -static void adm1026_fixup_gpio(struct i2c_client *client); -static struct adm1026_data *adm1026_update_device(struct device *dev); -static void adm1026_init_client(struct i2c_client *client); - - -static const struct i2c_device_id adm1026_id[] = { - { "adm1026", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1026_id); - -static struct i2c_driver adm1026_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1026", - }, - .probe = adm1026_probe, - .remove = adm1026_remove, - .id_table = adm1026_id, - .detect = adm1026_detect, - .address_list = normal_i2c, -}; - -static int adm1026_read_value(struct i2c_client *client, u8 reg) -{ - int res; - - if (reg < 0x80) { - /* "RAM" locations */ - res = i2c_smbus_read_byte_data(client, reg) & 0xff; - } else { - /* EEPROM, do nothing */ - res = 0; - } - return res; -} - -static int adm1026_write_value(struct i2c_client *client, u8 reg, int value) -{ - int res; - - if (reg < 0x80) { - /* "RAM" locations */ - res = i2c_smbus_write_byte_data(client, reg, value); - } else { - /* EEPROM, do nothing */ - res = 0; - } - return res; -} - -static void adm1026_init_client(struct i2c_client *client) -{ - int value, i; - struct adm1026_data *data = i2c_get_clientdata(client); - - dev_dbg(&client->dev, "Initializing device\n"); - /* Read chip config */ - data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); - data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); - data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); - - /* Inform user of chip config */ - dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n", - data->config1); - if ((data->config1 & CFG1_MONITOR) == 0) { - dev_dbg(&client->dev, "Monitoring not currently " - "enabled.\n"); - } - if (data->config1 & CFG1_INT_ENABLE) { - dev_dbg(&client->dev, "SMBALERT interrupts are " - "enabled.\n"); - } - if (data->config1 & CFG1_AIN8_9) { - dev_dbg(&client->dev, "in8 and in9 enabled. " - "temp3 disabled.\n"); - } else { - dev_dbg(&client->dev, "temp3 enabled. in8 and " - "in9 disabled.\n"); - } - if (data->config1 & CFG1_THERM_HOT) { - dev_dbg(&client->dev, "Automatic THERM, PWM, " - "and temp limits enabled.\n"); - } - - if (data->config3 & CFG3_GPIO16_ENABLE) { - dev_dbg(&client->dev, "GPIO16 enabled. THERM " - "pin disabled.\n"); - } else { - dev_dbg(&client->dev, "THERM pin enabled. " - "GPIO16 disabled.\n"); - } - if (data->config3 & CFG3_VREF_250) - dev_dbg(&client->dev, "Vref is 2.50 Volts.\n"); - else - dev_dbg(&client->dev, "Vref is 1.82 Volts.\n"); - /* Read and pick apart the existing GPIO configuration */ - value = 0; - for (i = 0; i <= 15; ++i) { - if ((i & 0x03) == 0) { - value = adm1026_read_value(client, - ADM1026_REG_GPIO_CFG_0_3 + i / 4); - } - data->gpio_config[i] = value & 0x03; - value >>= 2; - } - data->gpio_config[16] = (data->config3 >> 6) & 0x03; - - /* ... and then print it */ - adm1026_print_gpio(client); - - /* - * If the user asks us to reprogram the GPIO config, then - * do it now. - */ - if (gpio_input[0] != -1 || gpio_output[0] != -1 - || gpio_inverted[0] != -1 || gpio_normal[0] != -1 - || gpio_fan[0] != -1) { - adm1026_fixup_gpio(client); - } - - /* - * WE INTENTIONALLY make no changes to the limits, - * offsets, pwms, fans and zones. If they were - * configured, we don't want to mess with them. - * If they weren't, the default is 100% PWM, no - * control and will suffice until 'sensors -s' - * can be run by the user. We DO set the default - * value for pwm1.auto_pwm_min to its maximum - * so that enabling automatic pwm fan control - * without first setting a value for pwm1.auto_pwm_min - * will not result in potentially dangerous fan speed decrease. - */ - data->pwm1.auto_pwm_min = 255; - /* Start monitoring */ - value = adm1026_read_value(client, ADM1026_REG_CONFIG1); - /* Set MONITOR, clear interrupt acknowledge and s/w reset */ - value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); - dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); - data->config1 = value; - adm1026_write_value(client, ADM1026_REG_CONFIG1, value); - - /* initialize fan_div[] to hardware defaults */ - value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | - (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); - for (i = 0; i <= 7; ++i) { - data->fan_div[i] = DIV_FROM_REG(value & 0x03); - value >>= 2; - } -} - -static void adm1026_print_gpio(struct i2c_client *client) -{ - struct adm1026_data *data = i2c_get_clientdata(client); - int i; - - dev_dbg(&client->dev, "GPIO config is:\n"); - for (i = 0; i <= 7; ++i) { - if (data->config2 & (1 << i)) { - dev_dbg(&client->dev, "\t%sGP%s%d\n", - data->gpio_config[i] & 0x02 ? "" : "!", - data->gpio_config[i] & 0x01 ? "OUT" : "IN", - i); - } else { - dev_dbg(&client->dev, "\tFAN%d\n", i); - } - } - for (i = 8; i <= 15; ++i) { - dev_dbg(&client->dev, "\t%sGP%s%d\n", - data->gpio_config[i] & 0x02 ? "" : "!", - data->gpio_config[i] & 0x01 ? "OUT" : "IN", - i); - } - if (data->config3 & CFG3_GPIO16_ENABLE) { - dev_dbg(&client->dev, "\t%sGP%s16\n", - data->gpio_config[16] & 0x02 ? "" : "!", - data->gpio_config[16] & 0x01 ? "OUT" : "IN"); - } else { - /* GPIO16 is THERM */ - dev_dbg(&client->dev, "\tTHERM\n"); - } -} - -static void adm1026_fixup_gpio(struct i2c_client *client) -{ - struct adm1026_data *data = i2c_get_clientdata(client); - int i; - int value; - - /* Make the changes requested. */ - /* - * We may need to unlock/stop monitoring or soft-reset the - * chip before we can make changes. This hasn't been - * tested much. FIXME - */ - - /* Make outputs */ - for (i = 0; i <= 16; ++i) { - if (gpio_output[i] >= 0 && gpio_output[i] <= 16) - data->gpio_config[gpio_output[i]] |= 0x01; - /* if GPIO0-7 is output, it isn't a FAN tach */ - if (gpio_output[i] >= 0 && gpio_output[i] <= 7) - data->config2 |= 1 << gpio_output[i]; - } - - /* Input overrides output */ - for (i = 0; i <= 16; ++i) { - if (gpio_input[i] >= 0 && gpio_input[i] <= 16) - data->gpio_config[gpio_input[i]] &= ~0x01; - /* if GPIO0-7 is input, it isn't a FAN tach */ - if (gpio_input[i] >= 0 && gpio_input[i] <= 7) - data->config2 |= 1 << gpio_input[i]; - } - - /* Inverted */ - for (i = 0; i <= 16; ++i) { - if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) - data->gpio_config[gpio_inverted[i]] &= ~0x02; - } - - /* Normal overrides inverted */ - for (i = 0; i <= 16; ++i) { - if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) - data->gpio_config[gpio_normal[i]] |= 0x02; - } - - /* Fan overrides input and output */ - for (i = 0; i <= 7; ++i) { - if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) - data->config2 &= ~(1 << gpio_fan[i]); - } - - /* Write new configs to registers */ - adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); - data->config3 = (data->config3 & 0x3f) - | ((data->gpio_config[16] & 0x03) << 6); - adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); - for (i = 15, value = 0; i >= 0; --i) { - value <<= 2; - value |= data->gpio_config[i] & 0x03; - if ((i & 0x03) == 0) { - adm1026_write_value(client, - ADM1026_REG_GPIO_CFG_0_3 + i/4, - value); - value = 0; - } - } - - /* Print the new config */ - adm1026_print_gpio(client); -} - - -static struct adm1026_data *adm1026_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - int i; - long value, alarms, gpio; - - mutex_lock(&data->update_lock); - if (!data->valid - || time_after(jiffies, - data->last_reading + ADM1026_DATA_INTERVAL)) { - /* Things that change quickly */ - dev_dbg(&client->dev, "Reading sensor values\n"); - for (i = 0; i <= 16; ++i) { - data->in[i] = - adm1026_read_value(client, ADM1026_REG_IN[i]); - } - - for (i = 0; i <= 7; ++i) { - data->fan[i] = - adm1026_read_value(client, ADM1026_REG_FAN(i)); - } - - for (i = 0; i <= 2; ++i) { - /* - * NOTE: temp[] is s8 and we assume 2's complement - * "conversion" in the assignment - */ - data->temp[i] = - adm1026_read_value(client, ADM1026_REG_TEMP[i]); - } - - data->pwm1.pwm = adm1026_read_value(client, - ADM1026_REG_PWM); - data->analog_out = adm1026_read_value(client, - ADM1026_REG_DAC); - /* GPIO16 is MSbit of alarms, move it to gpio */ - alarms = adm1026_read_value(client, ADM1026_REG_STATUS4); - gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ - alarms &= 0x7f; - alarms <<= 8; - alarms |= adm1026_read_value(client, ADM1026_REG_STATUS3); - alarms <<= 8; - alarms |= adm1026_read_value(client, ADM1026_REG_STATUS2); - alarms <<= 8; - alarms |= adm1026_read_value(client, ADM1026_REG_STATUS1); - data->alarms = alarms; - - /* Read the GPIO values */ - gpio |= adm1026_read_value(client, - ADM1026_REG_GPIO_STATUS_8_15); - gpio <<= 8; - gpio |= adm1026_read_value(client, - ADM1026_REG_GPIO_STATUS_0_7); - data->gpio = gpio; - - data->last_reading = jiffies; - }; /* last_reading */ - - if (!data->valid || - time_after(jiffies, data->last_config + ADM1026_CONFIG_INTERVAL)) { - /* Things that don't change often */ - dev_dbg(&client->dev, "Reading config values\n"); - for (i = 0; i <= 16; ++i) { - data->in_min[i] = adm1026_read_value(client, - ADM1026_REG_IN_MIN[i]); - data->in_max[i] = adm1026_read_value(client, - ADM1026_REG_IN_MAX[i]); - } - - value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) - | (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) - << 8); - for (i = 0; i <= 7; ++i) { - data->fan_min[i] = adm1026_read_value(client, - ADM1026_REG_FAN_MIN(i)); - data->fan_div[i] = DIV_FROM_REG(value & 0x03); - value >>= 2; - } - - for (i = 0; i <= 2; ++i) { - /* - * NOTE: temp_xxx[] are s8 and we assume 2's - * complement "conversion" in the assignment - */ - data->temp_min[i] = adm1026_read_value(client, - ADM1026_REG_TEMP_MIN[i]); - data->temp_max[i] = adm1026_read_value(client, - ADM1026_REG_TEMP_MAX[i]); - data->temp_tmin[i] = adm1026_read_value(client, - ADM1026_REG_TEMP_TMIN[i]); - data->temp_crit[i] = adm1026_read_value(client, - ADM1026_REG_TEMP_THERM[i]); - data->temp_offset[i] = adm1026_read_value(client, - ADM1026_REG_TEMP_OFFSET[i]); - } - - /* Read the STATUS/alarm masks */ - alarms = adm1026_read_value(client, ADM1026_REG_MASK4); - gpio = alarms & 0x80 ? 0x0100 : 0; /* GPIO16 */ - alarms = (alarms & 0x7f) << 8; - alarms |= adm1026_read_value(client, ADM1026_REG_MASK3); - alarms <<= 8; - alarms |= adm1026_read_value(client, ADM1026_REG_MASK2); - alarms <<= 8; - alarms |= adm1026_read_value(client, ADM1026_REG_MASK1); - data->alarm_mask = alarms; - - /* Read the GPIO values */ - gpio |= adm1026_read_value(client, - ADM1026_REG_GPIO_MASK_8_15); - gpio <<= 8; - gpio |= adm1026_read_value(client, ADM1026_REG_GPIO_MASK_0_7); - data->gpio_mask = gpio; - - /* Read various values from CONFIG1 */ - data->config1 = adm1026_read_value(client, - ADM1026_REG_CONFIG1); - if (data->config1 & CFG1_PWM_AFC) { - data->pwm1.enable = 2; - data->pwm1.auto_pwm_min = - PWM_MIN_FROM_REG(data->pwm1.pwm); - } - /* Read the GPIO config */ - data->config2 = adm1026_read_value(client, - ADM1026_REG_CONFIG2); - data->config3 = adm1026_read_value(client, - ADM1026_REG_CONFIG3); - data->gpio_config[16] = (data->config3 >> 6) & 0x03; - - value = 0; - for (i = 0; i <= 15; ++i) { - if ((i & 0x03) == 0) { - value = adm1026_read_value(client, - ADM1026_REG_GPIO_CFG_0_3 + i/4); - } - data->gpio_config[i] = value & 0x03; - value >>= 2; - } - - data->last_config = jiffies; - }; /* last_config */ - - data->valid = 1; - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in[nr])); -} -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr])); -} -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = INS_TO_REG(nr, val); - adm1026_write_value(client, ADM1026_REG_IN_MIN[nr], data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr])); -} -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = INS_TO_REG(nr, val); - adm1026_write_value(client, ADM1026_REG_IN_MAX[nr], data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define in_reg(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in, \ - NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); - - -in_reg(0); -in_reg(1); -in_reg(2); -in_reg(3); -in_reg(4); -in_reg(5); -in_reg(6); -in_reg(7); -in_reg(8); -in_reg(9); -in_reg(10); -in_reg(11); -in_reg(12); -in_reg(13); -in_reg(14); -in_reg(15); - -static ssize_t show_in16(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in[16]) - - NEG12_OFFSET); -} -static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_min[16]) - - NEG12_OFFSET); -} -static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[16] = INS_TO_REG(16, val + NEG12_OFFSET); - adm1026_write_value(client, ADM1026_REG_IN_MIN[16], data->in_min[16]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(16, data->in_max[16]) - - NEG12_OFFSET); -} -static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[16] = INS_TO_REG(16, val+NEG12_OFFSET); - adm1026_write_value(client, ADM1026_REG_IN_MAX[16], data->in_max[16]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in16, NULL, 16); -static SENSOR_DEVICE_ATTR(in16_min, S_IRUGO | S_IWUSR, show_in16_min, - set_in16_min, 16); -static SENSOR_DEVICE_ATTR(in16_max, S_IRUGO | S_IWUSR, show_in16_max, - set_in16_max, 16); - - -/* Now add fan read/write functions */ - -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - data->fan_div[nr])); -} -static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - data->fan_div[nr])); -} -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, data->fan_div[nr]); - adm1026_write_value(client, ADM1026_REG_FAN_MIN(nr), - data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan, NULL, \ - offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); - -fan_offset(1); -fan_offset(2); -fan_offset(3); -fan_offset(4); -fan_offset(5); -fan_offset(6); -fan_offset(7); -fan_offset(8); - -/* Adjust fan_min to account for new fan divisor */ -static void fixup_fan_min(struct device *dev, int fan, int old_div) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - int new_min; - int new_div = data->fan_div[fan]; - - /* 0 and 0xff are special. Don't adjust them */ - if (data->fan_min[fan] == 0 || data->fan_min[fan] == 0xff) - return; - - new_min = data->fan_min[fan] * old_div / new_div; - new_min = SENSORS_LIMIT(new_min, 1, 254); - data->fan_min[fan] = new_min; - adm1026_write_value(client, ADM1026_REG_FAN_MIN(fan), new_min); -} - -/* Now add fan_div read/write functions */ -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", data->fan_div[nr]); -} -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int orig_div, new_div; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - new_div = DIV_TO_REG(val); - - mutex_lock(&data->update_lock); - orig_div = data->fan_div[nr]; - data->fan_div[nr] = DIV_FROM_REG(new_div); - - if (nr < 4) { /* 0 <= nr < 4 */ - adm1026_write_value(client, ADM1026_REG_FAN_DIV_0_3, - (DIV_TO_REG(data->fan_div[0]) << 0) | - (DIV_TO_REG(data->fan_div[1]) << 2) | - (DIV_TO_REG(data->fan_div[2]) << 4) | - (DIV_TO_REG(data->fan_div[3]) << 6)); - } else { /* 3 < nr < 8 */ - adm1026_write_value(client, ADM1026_REG_FAN_DIV_4_7, - (DIV_TO_REG(data->fan_div[4]) << 0) | - (DIV_TO_REG(data->fan_div[5]) << 2) | - (DIV_TO_REG(data->fan_div[6]) << 4) | - (DIV_TO_REG(data->fan_div[7]) << 6)); - } - - if (data->fan_div[nr] != orig_div) - fixup_fan_min(dev, nr, orig_div); - - mutex_unlock(&data->update_lock); - return count; -} - -#define fan_offset_div(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1); - -fan_offset_div(1); -fan_offset_div(2); -fan_offset_div(3); -fan_offset_div(4); -fan_offset_div(5); -fan_offset_div(6); -fan_offset_div(7); -fan_offset_div(8); - -/* Temps */ -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); -} -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); -} -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_MIN[nr], - data->temp_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); -} -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_MAX[nr], - data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define temp_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ - NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); - - -temp_reg(1); -temp_reg(2); -temp_reg(3); - -static ssize_t show_temp_offset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); -} -static ssize_t set_temp_offset(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_offset[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_OFFSET[nr], - data->temp_offset[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define temp_offset_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ - show_temp_offset, set_temp_offset, offset - 1); - -temp_offset_reg(1); -temp_offset_reg(2); -temp_offset_reg(3); - -static ssize_t show_temp_auto_point1_temp_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG( - ADM1026_FAN_ACTIVATION_TEMP_HYST + data->temp_tmin[nr])); -} -static ssize_t show_temp_auto_point2_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr] + - ADM1026_FAN_CONTROL_TEMP_RANGE)); -} -static ssize_t show_temp_auto_point1_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_tmin[nr])); -} -static ssize_t set_temp_auto_point1_temp(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_tmin[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_TMIN[nr], - data->temp_tmin[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define temp_auto_point(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp, \ - S_IRUGO | S_IWUSR, show_temp_auto_point1_temp, \ - set_temp_auto_point1_temp, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_point1_temp_hyst, S_IRUGO,\ - show_temp_auto_point1_temp_hyst, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_point2_temp, S_IRUGO, \ - show_temp_auto_point2_temp, NULL, offset - 1); - -temp_auto_point(1); -temp_auto_point(2); -temp_auto_point(3); - -static ssize_t show_temp_crit_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", (data->config1 & CFG1_THERM_HOT) >> 4); -} -static ssize_t set_temp_crit_enable(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->config1 = (data->config1 & ~CFG1_THERM_HOT) | (val << 4); - adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); - mutex_unlock(&data->update_lock); - - return count; -} - -#define temp_crit_enable(offset) \ -static DEVICE_ATTR(temp##offset##_crit_enable, S_IRUGO | S_IWUSR, \ - show_temp_crit_enable, set_temp_crit_enable); - -temp_crit_enable(1); -temp_crit_enable(2); -temp_crit_enable(3); - -static ssize_t show_temp_crit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); -} -static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_crit[nr] = TEMP_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_TEMP_THERM[nr], - data->temp_crit[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define temp_crit_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ - show_temp_crit, set_temp_crit, offset - 1); - -temp_crit_reg(1); -temp_crit_reg(2); -temp_crit_reg(3); - -static ssize_t show_analog_out_reg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", DAC_FROM_REG(data->analog_out)); -} -static ssize_t set_analog_out_reg(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->analog_out = DAC_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_DAC, data->analog_out); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(analog_out, S_IRUGO | S_IWUSR, show_analog_out_reg, - set_analog_out_reg); - -static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - int vid = (data->gpio >> 11) & 0x1f; - - dev_dbg(dev, "Setting VID from GPIO11-15.\n"); - return sprintf(buf, "%d\n", vid_from_reg(vid, data->vrm)); -} - -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); - -static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct adm1026_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} - -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); - -static ssize_t show_alarms_reg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%ld\n", data->alarms); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - return sprintf(buf, "%ld\n", (data->alarms >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(in14_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(in15_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(in16_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 19); -static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 20); -static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 21); -static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 22); -static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, 23); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 24); -static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, 25); -static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 26); - -static ssize_t show_alarm_mask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%ld\n", data->alarm_mask); -} -static ssize_t set_alarm_mask(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - unsigned long mask; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->alarm_mask = val & 0x7fffffff; - mask = data->alarm_mask - | (data->gpio_mask & 0x10000 ? 0x80000000 : 0); - adm1026_write_value(client, ADM1026_REG_MASK1, - mask & 0xff); - mask >>= 8; - adm1026_write_value(client, ADM1026_REG_MASK2, - mask & 0xff); - mask >>= 8; - adm1026_write_value(client, ADM1026_REG_MASK3, - mask & 0xff); - mask >>= 8; - adm1026_write_value(client, ADM1026_REG_MASK4, - mask & 0xff); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(alarm_mask, S_IRUGO | S_IWUSR, show_alarm_mask, - set_alarm_mask); - - -static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%ld\n", data->gpio); -} -static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long gpio; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->gpio = val & 0x1ffff; - gpio = data->gpio; - adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_0_7, gpio & 0xff); - gpio >>= 8; - adm1026_write_value(client, ADM1026_REG_GPIO_STATUS_8_15, gpio & 0xff); - gpio = ((gpio >> 1) & 0x80) | (data->alarms >> 24 & 0x7f); - adm1026_write_value(client, ADM1026_REG_STATUS4, gpio & 0xff); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(gpio, S_IRUGO | S_IWUSR, show_gpio, set_gpio); - -static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%ld\n", data->gpio_mask); -} -static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - long mask; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->gpio_mask = val & 0x1ffff; - mask = data->gpio_mask; - adm1026_write_value(client, ADM1026_REG_GPIO_MASK_0_7, mask & 0xff); - mask >>= 8; - adm1026_write_value(client, ADM1026_REG_GPIO_MASK_8_15, mask & 0xff); - mask = ((mask >> 1) & 0x80) | (data->alarm_mask >> 24 & 0x7f); - adm1026_write_value(client, ADM1026_REG_MASK1, mask & 0xff); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(gpio_mask, S_IRUGO | S_IWUSR, show_gpio_mask, set_gpio_mask); - -static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm1.pwm)); -} - -static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - - if (data->pwm1.enable == 1) { - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm1.pwm = PWM_TO_REG(val); - adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - mutex_unlock(&data->update_lock); - } - return count; -} - -static ssize_t show_auto_pwm_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", data->pwm1.auto_pwm_min); -} - -static ssize_t set_auto_pwm_min(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm1.auto_pwm_min = SENSORS_LIMIT(val, 0, 255); - if (data->pwm1.enable == 2) { /* apply immediately */ - data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | - PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); - adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - } - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_auto_pwm_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", ADM1026_PWM_MAX); -} - -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm1026_data *data = adm1026_update_device(dev); - return sprintf(buf, "%d\n", data->pwm1.enable); -} - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); - int old_enable; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val >= 3) - return -EINVAL; - - mutex_lock(&data->update_lock); - old_enable = data->pwm1.enable; - data->pwm1.enable = val; - data->config1 = (data->config1 & ~CFG1_PWM_AFC) - | ((val == 2) ? CFG1_PWM_AFC : 0); - adm1026_write_value(client, ADM1026_REG_CONFIG1, data->config1); - if (val == 2) { /* apply pwm1_auto_pwm_min to pwm1 */ - data->pwm1.pwm = PWM_TO_REG((data->pwm1.pwm & 0x0f) | - PWM_MIN_TO_REG(data->pwm1.auto_pwm_min)); - adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - } else if (!((old_enable == 1) && (val == 1))) { - /* set pwm to safe value */ - data->pwm1.pwm = 255; - adm1026_write_value(client, ADM1026_REG_PWM, data->pwm1.pwm); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* enable PWM fan control */ -static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); -static DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); -static DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm_reg, set_pwm_reg); -static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, - set_pwm_enable); -static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, show_pwm_enable, - set_pwm_enable); -static DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, show_pwm_enable, - set_pwm_enable); -static DEVICE_ATTR(temp1_auto_point1_pwm, S_IRUGO | S_IWUSR, - show_auto_pwm_min, set_auto_pwm_min); -static DEVICE_ATTR(temp2_auto_point1_pwm, S_IRUGO | S_IWUSR, - show_auto_pwm_min, set_auto_pwm_min); -static DEVICE_ATTR(temp3_auto_point1_pwm, S_IRUGO | S_IWUSR, - show_auto_pwm_min, set_auto_pwm_min); - -static DEVICE_ATTR(temp1_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); -static DEVICE_ATTR(temp2_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); -static DEVICE_ATTR(temp3_auto_point2_pwm, S_IRUGO, show_auto_pwm_max, NULL); - -static struct attribute *adm1026_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in10_max.dev_attr.attr, - &sensor_dev_attr_in10_min.dev_attr.attr, - &sensor_dev_attr_in10_alarm.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - &sensor_dev_attr_in11_max.dev_attr.attr, - &sensor_dev_attr_in11_min.dev_attr.attr, - &sensor_dev_attr_in11_alarm.dev_attr.attr, - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_in12_max.dev_attr.attr, - &sensor_dev_attr_in12_min.dev_attr.attr, - &sensor_dev_attr_in12_alarm.dev_attr.attr, - &sensor_dev_attr_in13_input.dev_attr.attr, - &sensor_dev_attr_in13_max.dev_attr.attr, - &sensor_dev_attr_in13_min.dev_attr.attr, - &sensor_dev_attr_in13_alarm.dev_attr.attr, - &sensor_dev_attr_in14_input.dev_attr.attr, - &sensor_dev_attr_in14_max.dev_attr.attr, - &sensor_dev_attr_in14_min.dev_attr.attr, - &sensor_dev_attr_in14_alarm.dev_attr.attr, - &sensor_dev_attr_in15_input.dev_attr.attr, - &sensor_dev_attr_in15_max.dev_attr.attr, - &sensor_dev_attr_in15_min.dev_attr.attr, - &sensor_dev_attr_in15_alarm.dev_attr.attr, - &sensor_dev_attr_in16_input.dev_attr.attr, - &sensor_dev_attr_in16_max.dev_attr.attr, - &sensor_dev_attr_in16_min.dev_attr.attr, - &sensor_dev_attr_in16_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_div.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - &sensor_dev_attr_fan5_input.dev_attr.attr, - &sensor_dev_attr_fan5_div.dev_attr.attr, - &sensor_dev_attr_fan5_min.dev_attr.attr, - &sensor_dev_attr_fan5_alarm.dev_attr.attr, - &sensor_dev_attr_fan6_input.dev_attr.attr, - &sensor_dev_attr_fan6_div.dev_attr.attr, - &sensor_dev_attr_fan6_min.dev_attr.attr, - &sensor_dev_attr_fan6_alarm.dev_attr.attr, - &sensor_dev_attr_fan7_input.dev_attr.attr, - &sensor_dev_attr_fan7_div.dev_attr.attr, - &sensor_dev_attr_fan7_min.dev_attr.attr, - &sensor_dev_attr_fan7_alarm.dev_attr.attr, - &sensor_dev_attr_fan8_input.dev_attr.attr, - &sensor_dev_attr_fan8_div.dev_attr.attr, - &sensor_dev_attr_fan8_min.dev_attr.attr, - &sensor_dev_attr_fan8_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &dev_attr_temp1_crit_enable.attr, - &dev_attr_temp2_crit_enable.attr, - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - &dev_attr_alarms.attr, - &dev_attr_alarm_mask.attr, - &dev_attr_gpio.attr, - &dev_attr_gpio_mask.attr, - &dev_attr_pwm1.attr, - &dev_attr_pwm2.attr, - &dev_attr_pwm3.attr, - &dev_attr_pwm1_enable.attr, - &dev_attr_pwm2_enable.attr, - &dev_attr_pwm3_enable.attr, - &dev_attr_temp1_auto_point1_pwm.attr, - &dev_attr_temp2_auto_point1_pwm.attr, - &dev_attr_temp1_auto_point2_pwm.attr, - &dev_attr_temp2_auto_point2_pwm.attr, - &dev_attr_analog_out.attr, - NULL -}; - -static const struct attribute_group adm1026_group = { - .attrs = adm1026_attributes, -}; - -static struct attribute *adm1026_attributes_temp3[] = { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &dev_attr_temp3_crit_enable.attr, - &dev_attr_temp3_auto_point1_pwm.attr, - &dev_attr_temp3_auto_point2_pwm.attr, - NULL -}; - -static const struct attribute_group adm1026_group_temp3 = { - .attrs = adm1026_attributes_temp3, -}; - -static struct attribute *adm1026_attributes_in8_9[] = { - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in8_alarm.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in9_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group adm1026_group_in8_9 = { - .attrs = adm1026_attributes_in8_9, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1026_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - int company, verstep; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - /* We need to be able to do byte I/O */ - return -ENODEV; - }; - - /* Now, we do the remaining detection. */ - - company = adm1026_read_value(client, ADM1026_REG_COMPANY); - verstep = adm1026_read_value(client, ADM1026_REG_VERSTEP); - - dev_dbg(&adapter->dev, "Detecting device at %d,0x%02x with" - " COMPANY: 0x%02x and VERSTEP: 0x%02x\n", - i2c_adapter_id(client->adapter), client->addr, - company, verstep); - - /* Determine the chip type. */ - dev_dbg(&adapter->dev, "Autodetecting device at %d,0x%02x...\n", - i2c_adapter_id(adapter), address); - if (company == ADM1026_COMPANY_ANALOG_DEV - && verstep == ADM1026_VERSTEP_ADM1026) { - /* Analog Devices ADM1026 */ - } else if (company == ADM1026_COMPANY_ANALOG_DEV - && (verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { - dev_err(&adapter->dev, "Unrecognized stepping " - "0x%02x. Defaulting to ADM1026.\n", verstep); - } else if ((verstep & 0xf0) == ADM1026_VERSTEP_GENERIC) { - dev_err(&adapter->dev, "Found version/stepping " - "0x%02x. Assuming generic ADM1026.\n", - verstep); - } else { - dev_dbg(&adapter->dev, "Autodetection failed\n"); - /* Not an ADM1026... */ - return -ENODEV; - } - - strlcpy(info->type, "adm1026", I2C_NAME_SIZE); - - return 0; -} - -static int adm1026_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1026_data *data; - int err; - - data = kzalloc(sizeof(struct adm1026_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Set the VRM version */ - data->vrm = vid_which_vrm(); - - /* Initialize the ADM1026 chip */ - adm1026_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1026_group); - if (err) - goto exitfree; - if (data->config1 & CFG1_AIN8_9) - err = sysfs_create_group(&client->dev.kobj, - &adm1026_group_in8_9); - else - err = sysfs_create_group(&client->dev.kobj, - &adm1026_group_temp3); - if (err) - goto exitremove; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exitremove; - } - - return 0; - - /* Error out and cleanup code */ -exitremove: - sysfs_remove_group(&client->dev.kobj, &adm1026_group); - if (data->config1 & CFG1_AIN8_9) - sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); - else - sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); -exitfree: - kfree(data); -exit: - return err; -} - -static int adm1026_remove(struct i2c_client *client) -{ - struct adm1026_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1026_group); - if (data->config1 & CFG1_AIN8_9) - sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); - else - sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); - kfree(data); - return 0; -} - -module_i2c_driver(adm1026_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Philip Pokorny , " - "Justin Thiessen "); -MODULE_DESCRIPTION("ADM1026 driver"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adm1029.c b/ANDROID_3.4.5/drivers/hwmon/adm1029.c deleted file mode 100644 index 80cc465d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adm1029.c +++ /dev/null @@ -1,460 +0,0 @@ -/* - * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring - * - * Copyright (C) 2006 Corentin LABBE - * - * Based on LM83 Driver by Jean Delvare - * - * Give only processor, motherboard temperatures and fan tachs - * Very rare chip please let me know if you use it - * - * http://www.analog.com/UploadedFiles/Data_Sheets/ADM1029.pdf - * - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2 of the License - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - */ - -static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, I2C_CLIENT_END -}; - -/* - * The ADM1029 registers - * Manufacturer ID is 0x41 for Analog Devices - */ - -#define ADM1029_REG_MAN_ID 0x0D -#define ADM1029_REG_CHIP_ID 0x0E -#define ADM1029_REG_CONFIG 0x01 -#define ADM1029_REG_NB_FAN_SUPPORT 0x02 - -#define ADM1029_REG_TEMP_DEVICES_INSTALLED 0x06 - -#define ADM1029_REG_LOCAL_TEMP 0xA0 -#define ADM1029_REG_REMOTE1_TEMP 0xA1 -#define ADM1029_REG_REMOTE2_TEMP 0xA2 - -#define ADM1029_REG_LOCAL_TEMP_HIGH 0x90 -#define ADM1029_REG_REMOTE1_TEMP_HIGH 0x91 -#define ADM1029_REG_REMOTE2_TEMP_HIGH 0x92 - -#define ADM1029_REG_LOCAL_TEMP_LOW 0x98 -#define ADM1029_REG_REMOTE1_TEMP_LOW 0x99 -#define ADM1029_REG_REMOTE2_TEMP_LOW 0x9A - -#define ADM1029_REG_FAN1 0x70 -#define ADM1029_REG_FAN2 0x71 - -#define ADM1029_REG_FAN1_MIN 0x78 -#define ADM1029_REG_FAN2_MIN 0x79 - -#define ADM1029_REG_FAN1_CONFIG 0x68 -#define ADM1029_REG_FAN2_CONFIG 0x69 - -#define TEMP_FROM_REG(val) ((val) * 1000) - -#define DIV_FROM_REG(val) (1 << (((val) >> 6) - 1)) - -/* Registers to be checked by adm1029_update_device() */ -static const u8 ADM1029_REG_TEMP[] = { - ADM1029_REG_LOCAL_TEMP, - ADM1029_REG_REMOTE1_TEMP, - ADM1029_REG_REMOTE2_TEMP, - ADM1029_REG_LOCAL_TEMP_HIGH, - ADM1029_REG_REMOTE1_TEMP_HIGH, - ADM1029_REG_REMOTE2_TEMP_HIGH, - ADM1029_REG_LOCAL_TEMP_LOW, - ADM1029_REG_REMOTE1_TEMP_LOW, - ADM1029_REG_REMOTE2_TEMP_LOW, -}; - -static const u8 ADM1029_REG_FAN[] = { - ADM1029_REG_FAN1, - ADM1029_REG_FAN2, - ADM1029_REG_FAN1_MIN, - ADM1029_REG_FAN2_MIN, -}; - -static const u8 ADM1029_REG_FAN_DIV[] = { - ADM1029_REG_FAN1_CONFIG, - ADM1029_REG_FAN2_CONFIG, -}; - -/* - * Functions declaration - */ - -static int adm1029_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1029_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adm1029_remove(struct i2c_client *client); -static struct adm1029_data *adm1029_update_device(struct device *dev); -static int adm1029_init_client(struct i2c_client *client); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id adm1029_id[] = { - { "adm1029", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1029_id); - -static struct i2c_driver adm1029_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1029", - }, - .probe = adm1029_probe, - .remove = adm1029_remove, - .id_table = adm1029_id, - .detect = adm1029_detect, - .address_list = normal_i2c, -}; - -/* - * Client data (each client gets its own) - */ - -struct adm1029_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values, signed for temperature, unsigned for other stuff */ - s8 temp[ARRAY_SIZE(ADM1029_REG_TEMP)]; - u8 fan[ARRAY_SIZE(ADM1029_REG_FAN)]; - u8 fan_div[ARRAY_SIZE(ADM1029_REG_FAN_DIV)]; -}; - -/* - * Sysfs stuff - */ - -static ssize_t -show_temp(struct device *dev, struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm1029_data *data = adm1029_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); -} - -static ssize_t -show_fan(struct device *dev, struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm1029_data *data = adm1029_update_device(dev); - u16 val; - if (data->fan[attr->index] == 0 - || (data->fan_div[attr->index] & 0xC0) == 0 - || data->fan[attr->index] == 255) { - return sprintf(buf, "0\n"); - } - - val = 1880 * 120 / DIV_FROM_REG(data->fan_div[attr->index]) - / data->fan[attr->index]; - return sprintf(buf, "%d\n", val); -} - -static ssize_t -show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm1029_data *data = adm1029_update_device(dev); - if ((data->fan_div[attr->index] & 0xC0) == 0) - return sprintf(buf, "0\n"); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); -} - -static ssize_t set_fan_div(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1029_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - u8 reg; - long val; - int ret = kstrtol(buf, 10, &val); - if (ret < 0) - return ret; - - mutex_lock(&data->update_lock); - - /*Read actual config */ - reg = i2c_smbus_read_byte_data(client, - ADM1029_REG_FAN_DIV[attr->index]); - - switch (val) { - case 1: - val = 1; - break; - case 2: - val = 2; - break; - case 4: - val = 3; - break; - default: - mutex_unlock(&data->update_lock); - dev_err(&client->dev, "fan_div value %ld not " - "supported. Choose one of 1, 2 or 4!\n", val); - return -EINVAL; - } - /* Update the value */ - reg = (reg & 0x3F) | (val << 6); - - /* Write value */ - i2c_smbus_write_byte_data(client, - ADM1029_REG_FAN_DIV[attr->index], reg); - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Access rights on sysfs. S_IRUGO: Is Readable by User, Group and Others - * S_IWUSR: Is Writable by User. - */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); - -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp, NULL, 8); - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); - -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan, NULL, 3); - -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - show_fan_div, set_fan_div, 1); - -static struct attribute *adm1029_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - NULL -}; - -static const struct attribute_group adm1029_group = { - .attrs = adm1029_attributes, -}; - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1029_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u8 man_id, chip_id, temp_devices_installed, nb_fan_support; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* - * ADM1029 doesn't have CHIP ID, check just MAN ID - * For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED, - * ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values - * documented - */ - - man_id = i2c_smbus_read_byte_data(client, ADM1029_REG_MAN_ID); - chip_id = i2c_smbus_read_byte_data(client, ADM1029_REG_CHIP_ID); - temp_devices_installed = i2c_smbus_read_byte_data(client, - ADM1029_REG_TEMP_DEVICES_INSTALLED); - nb_fan_support = i2c_smbus_read_byte_data(client, - ADM1029_REG_NB_FAN_SUPPORT); - /* 0x41 is Analog Devices */ - if (man_id != 0x41 || (temp_devices_installed & 0xf9) != 0x01 - || nb_fan_support != 0x03) - return -ENODEV; - - if ((chip_id & 0xF0) != 0x00) { - /* - * There are no "official" CHIP ID, so actually - * we use Major/Minor revision for that - */ - pr_info("adm1029: Unknown major revision %x, " - "please let us know\n", chip_id); - return -ENODEV; - } - - strlcpy(info->type, "adm1029", I2C_NAME_SIZE); - - return 0; -} - -static int adm1029_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1029_data *data; - int err; - - data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* - * Initialize the ADM1029 chip - * Check config register - */ - if (adm1029_init_client(client) == 0) { - err = -ENODEV; - goto exit_free; - } - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1029_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - - exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &adm1029_group); - exit_free: - kfree(data); - exit: - return err; -} - -static int adm1029_init_client(struct i2c_client *client) -{ - u8 config; - config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); - if ((config & 0x10) == 0) { - i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG, - config | 0x10); - } - /* recheck config */ - config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); - if ((config & 0x10) == 0) { - dev_err(&client->dev, "Initialization failed!\n"); - return 0; - } - return 1; -} - -static int adm1029_remove(struct i2c_client *client) -{ - struct adm1029_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1029_group); - - kfree(data); - return 0; -} - -/* - * function that update the status of the chips (temperature for example) - */ -static struct adm1029_data *adm1029_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1029_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - /* - * Use the "cache" Luke, don't recheck values - * if there are already checked not a long time later - */ - if (time_after(jiffies, data->last_updated + HZ * 2) - || !data->valid) { - int nr; - - dev_dbg(&client->dev, "Updating adm1029 data\n"); - - for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) { - data->temp[nr] = - i2c_smbus_read_byte_data(client, - ADM1029_REG_TEMP[nr]); - } - for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) { - data->fan[nr] = - i2c_smbus_read_byte_data(client, - ADM1029_REG_FAN[nr]); - } - for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) { - data->fan_div[nr] = - i2c_smbus_read_byte_data(client, - ADM1029_REG_FAN_DIV[nr]); - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(adm1029_driver); - -MODULE_AUTHOR("Corentin LABBE "); -MODULE_DESCRIPTION("adm1029 driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adm1031.c b/ANDROID_3.4.5/drivers/hwmon/adm1031.c deleted file mode 100644 index 44e1fd7f..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adm1031.c +++ /dev/null @@ -1,1140 +0,0 @@ -/* - * adm1031.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Based on lm75.c and lm85.c - * Supports adm1030 / adm1031 - * Copyright (C) 2004 Alexandre d'Alton - * Reworked by Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Following macros takes channel parameter starting from 0 to 2 */ -#define ADM1031_REG_FAN_SPEED(nr) (0x08 + (nr)) -#define ADM1031_REG_FAN_DIV(nr) (0x20 + (nr)) -#define ADM1031_REG_PWM (0x22) -#define ADM1031_REG_FAN_MIN(nr) (0x10 + (nr)) -#define ADM1031_REG_FAN_FILTER (0x23) - -#define ADM1031_REG_TEMP_OFFSET(nr) (0x0d + (nr)) -#define ADM1031_REG_TEMP_MAX(nr) (0x14 + 4 * (nr)) -#define ADM1031_REG_TEMP_MIN(nr) (0x15 + 4 * (nr)) -#define ADM1031_REG_TEMP_CRIT(nr) (0x16 + 4 * (nr)) - -#define ADM1031_REG_TEMP(nr) (0x0a + (nr)) -#define ADM1031_REG_AUTO_TEMP(nr) (0x24 + (nr)) - -#define ADM1031_REG_STATUS(nr) (0x2 + (nr)) - -#define ADM1031_REG_CONF1 0x00 -#define ADM1031_REG_CONF2 0x01 -#define ADM1031_REG_EXT_TEMP 0x06 - -#define ADM1031_CONF1_MONITOR_ENABLE 0x01 /* Monitoring enable */ -#define ADM1031_CONF1_PWM_INVERT 0x08 /* PWM Invert */ -#define ADM1031_CONF1_AUTO_MODE 0x80 /* Auto FAN */ - -#define ADM1031_CONF2_PWM1_ENABLE 0x01 -#define ADM1031_CONF2_PWM2_ENABLE 0x02 -#define ADM1031_CONF2_TACH1_ENABLE 0x04 -#define ADM1031_CONF2_TACH2_ENABLE 0x08 -#define ADM1031_CONF2_TEMP_ENABLE(chan) (0x10 << (chan)) - -#define ADM1031_UPDATE_RATE_MASK 0x1c -#define ADM1031_UPDATE_RATE_SHIFT 2 - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -enum chips { adm1030, adm1031 }; - -typedef u8 auto_chan_table_t[8][2]; - -/* Each client has this additional data */ -struct adm1031_data { - struct device *hwmon_dev; - struct mutex update_lock; - int chip_type; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - unsigned int update_interval; /* In milliseconds */ - /* - * The chan_select_table contains the possible configurations for - * auto fan control. - */ - const auto_chan_table_t *chan_select_table; - u16 alarm; - u8 conf1; - u8 conf2; - u8 fan[2]; - u8 fan_div[2]; - u8 fan_min[2]; - u8 pwm[2]; - u8 old_pwm[2]; - s8 temp[3]; - u8 ext_temp[3]; - u8 auto_temp[3]; - u8 auto_temp_min[3]; - u8 auto_temp_off[3]; - u8 auto_temp_max[3]; - s8 temp_offset[3]; - s8 temp_min[3]; - s8 temp_max[3]; - s8 temp_crit[3]; -}; - -static int adm1031_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1031_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1031_init_client(struct i2c_client *client); -static int adm1031_remove(struct i2c_client *client); -static struct adm1031_data *adm1031_update_device(struct device *dev); - -static const struct i2c_device_id adm1031_id[] = { - { "adm1030", adm1030 }, - { "adm1031", adm1031 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1031_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver adm1031_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1031", - }, - .probe = adm1031_probe, - .remove = adm1031_remove, - .id_table = adm1031_id, - .detect = adm1031_detect, - .address_list = normal_i2c, -}; - -static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static inline int -adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - - -#define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ - ((val + 500) / 1000))) - -#define TEMP_FROM_REG(val) ((val) * 1000) - -#define TEMP_FROM_REG_EXT(val, ext) (TEMP_FROM_REG(val) + (ext) * 125) - -#define TEMP_OFFSET_TO_REG(val) (TEMP_TO_REG(val) & 0x8f) -#define TEMP_OFFSET_FROM_REG(val) TEMP_FROM_REG((val) < 0 ? \ - (val) | 0x70 : (val)) - -#define FAN_FROM_REG(reg, div) ((reg) ? \ - (11250 * 60) / ((reg) * (div)) : 0) - -static int FAN_TO_REG(int reg, int div) -{ - int tmp; - tmp = FAN_FROM_REG(SENSORS_LIMIT(reg, 0, 65535), div); - return tmp > 255 ? 255 : tmp; -} - -#define FAN_DIV_FROM_REG(reg) (1<<(((reg)&0xc0)>>6)) - -#define PWM_TO_REG(val) (SENSORS_LIMIT((val), 0, 255) >> 4) -#define PWM_FROM_REG(val) ((val) << 4) - -#define FAN_CHAN_FROM_REG(reg) (((reg) >> 5) & 7) -#define FAN_CHAN_TO_REG(val, reg) \ - (((reg) & 0x1F) | (((val) << 5) & 0xe0)) - -#define AUTO_TEMP_MIN_TO_REG(val, reg) \ - ((((val) / 500) & 0xf8) | ((reg) & 0x7)) -#define AUTO_TEMP_RANGE_FROM_REG(reg) (5000 * (1 << ((reg) & 0x7))) -#define AUTO_TEMP_MIN_FROM_REG(reg) (1000 * ((((reg) >> 3) & 0x1f) << 2)) - -#define AUTO_TEMP_MIN_FROM_REG_DEG(reg) ((((reg) >> 3) & 0x1f) << 2) - -#define AUTO_TEMP_OFF_FROM_REG(reg) \ - (AUTO_TEMP_MIN_FROM_REG(reg) - 5000) - -#define AUTO_TEMP_MAX_FROM_REG(reg) \ - (AUTO_TEMP_RANGE_FROM_REG(reg) + \ - AUTO_TEMP_MIN_FROM_REG(reg)) - -static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm) -{ - int ret; - int range = val - AUTO_TEMP_MIN_FROM_REG(reg); - - range = ((val - AUTO_TEMP_MIN_FROM_REG(reg))*10)/(16 - pwm); - ret = ((reg & 0xf8) | - (range < 10000 ? 0 : - range < 20000 ? 1 : - range < 40000 ? 2 : range < 80000 ? 3 : 4)); - return ret; -} - -/* FAN auto control */ -#define GET_FAN_AUTO_BITFIELD(data, idx) \ - (*(data)->chan_select_table)[FAN_CHAN_FROM_REG((data)->conf1)][idx % 2] - -/* - * The tables below contains the possible values for the auto fan - * control bitfields. the index in the table is the register value. - * MSb is the auto fan control enable bit, so the four first entries - * in the table disables auto fan control when both bitfields are zero. - */ -static const auto_chan_table_t auto_channel_select_table_adm1031 = { - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 2 /* 0b010 */ , 4 /* 0b100 */ }, - { 2 /* 0b010 */ , 2 /* 0b010 */ }, - { 4 /* 0b100 */ , 4 /* 0b100 */ }, - { 7 /* 0b111 */ , 7 /* 0b111 */ }, -}; - -static const auto_chan_table_t auto_channel_select_table_adm1030 = { - { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, - { 2 /* 0b10 */ , 0 }, - { 0xff /* invalid */ , 0 }, - { 0xff /* invalid */ , 0 }, - { 3 /* 0b11 */ , 0 }, -}; - -/* - * That function checks if a bitfield is valid and returns the other bitfield - * nearest match if no exact match where found. - */ -static int -get_fan_auto_nearest(struct adm1031_data *data, int chan, u8 val, u8 reg) -{ - int i; - int first_match = -1, exact_match = -1; - u8 other_reg_val = - (*data->chan_select_table)[FAN_CHAN_FROM_REG(reg)][chan ? 0 : 1]; - - if (val == 0) - return 0; - - for (i = 0; i < 8; i++) { - if ((val == (*data->chan_select_table)[i][chan]) && - ((*data->chan_select_table)[i][chan ? 0 : 1] == - other_reg_val)) { - /* We found an exact match */ - exact_match = i; - break; - } else if (val == (*data->chan_select_table)[i][chan] && - first_match == -1) { - /* - * Save the first match in case of an exact match has - * not been found - */ - first_match = i; - } - } - - if (exact_match >= 0) - return exact_match; - else if (first_match >= 0) - return first_match; - - return -EINVAL; -} - -static ssize_t show_fan_auto_channel(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", GET_FAN_AUTO_BITFIELD(data, nr)); -} - -static ssize_t -set_fan_auto_channel(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - u8 reg; - int ret; - u8 old_fan_mode; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - old_fan_mode = data->conf1; - - mutex_lock(&data->update_lock); - - ret = get_fan_auto_nearest(data, nr, val, data->conf1); - if (ret < 0) { - mutex_unlock(&data->update_lock); - return ret; - } - reg = ret; - data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); - if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) ^ - (old_fan_mode & ADM1031_CONF1_AUTO_MODE)) { - if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { - /* - * Switch to Auto Fan Mode - * Save PWM registers - * Set PWM registers to 33% Both - */ - data->old_pwm[0] = data->pwm[0]; - data->old_pwm[1] = data->pwm[1]; - adm1031_write_value(client, ADM1031_REG_PWM, 0x55); - } else { - /* Switch to Manual Mode */ - data->pwm[0] = data->old_pwm[0]; - data->pwm[1] = data->old_pwm[1]; - /* Restore PWM registers */ - adm1031_write_value(client, ADM1031_REG_PWM, - data->pwm[0] | (data->pwm[1] << 4)); - } - } - data->conf1 = FAN_CHAN_TO_REG(reg, data->conf1); - adm1031_write_value(client, ADM1031_REG_CONF1, data->conf1); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(auto_fan1_channel, S_IRUGO | S_IWUSR, - show_fan_auto_channel, set_fan_auto_channel, 0); -static SENSOR_DEVICE_ATTR(auto_fan2_channel, S_IRUGO | S_IWUSR, - show_fan_auto_channel, set_fan_auto_channel, 1); - -/* Auto Temps */ -static ssize_t show_auto_temp_off(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - AUTO_TEMP_OFF_FROM_REG(data->auto_temp[nr])); -} -static ssize_t show_auto_temp_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - AUTO_TEMP_MIN_FROM_REG(data->auto_temp[nr])); -} -static ssize_t -set_auto_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - data->auto_temp[nr] = AUTO_TEMP_MIN_TO_REG(val, data->auto_temp[nr]); - adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), - data->auto_temp[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t show_auto_temp_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - AUTO_TEMP_MAX_FROM_REG(data->auto_temp[nr])); -} -static ssize_t -set_auto_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = AUTO_TEMP_MAX_TO_REG(val, data->auto_temp[nr], - data->pwm[nr]); - adm1031_write_value(client, ADM1031_REG_AUTO_TEMP(nr), - data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define auto_temp_reg(offset) \ -static SENSOR_DEVICE_ATTR(auto_temp##offset##_off, S_IRUGO, \ - show_auto_temp_off, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(auto_temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_auto_temp_min, set_auto_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(auto_temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_auto_temp_max, set_auto_temp_max, offset - 1) - -auto_temp_reg(1); -auto_temp_reg(2); -auto_temp_reg(3); - -/* pwm */ -static ssize_t show_pwm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); -} -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret, reg; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - if ((data->conf1 & ADM1031_CONF1_AUTO_MODE) && - (((val>>4) & 0xf) != 5)) { - /* In automatic mode, the only PWM accepted is 33% */ - mutex_unlock(&data->update_lock); - return -EINVAL; - } - data->pwm[nr] = PWM_TO_REG(val); - reg = adm1031_read_value(client, ADM1031_REG_PWM); - adm1031_write_value(client, ADM1031_REG_PWM, - nr ? ((data->pwm[nr] << 4) & 0xf0) | (reg & 0xf) - : (data->pwm[nr] & 0xf) | (reg & 0xf0)); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(auto_fan1_min_pwm, S_IRUGO | S_IWUSR, - show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(auto_fan2_min_pwm, S_IRUGO | S_IWUSR, - show_pwm, set_pwm, 1); - -/* Fans */ - -/* - * That function checks the cases where the fan reading is not - * relevant. It is used to provide 0 as fan reading when the fan is - * not supposed to run - */ -static int trust_fan_readings(struct adm1031_data *data, int chan) -{ - int res = 0; - - if (data->conf1 & ADM1031_CONF1_AUTO_MODE) { - switch (data->conf1 & 0x60) { - case 0x00: - /* - * remote temp1 controls fan1, - * remote temp2 controls fan2 - */ - res = data->temp[chan+1] >= - AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[chan+1]); - break; - case 0x20: /* remote temp1 controls both fans */ - res = - data->temp[1] >= - AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]); - break; - case 0x40: /* remote temp2 controls both fans */ - res = - data->temp[2] >= - AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2]); - break; - case 0x60: /* max controls both fans */ - res = - data->temp[0] >= - AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[0]) - || data->temp[1] >= - AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[1]) - || (data->chip_type == adm1031 - && data->temp[2] >= - AUTO_TEMP_MIN_FROM_REG_DEG(data->auto_temp[2])); - break; - } - } else { - res = data->pwm[chan] > 0; - } - return res; -} - - -static ssize_t show_fan(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - int value; - - value = trust_fan_readings(data, nr) ? FAN_FROM_REG(data->fan[nr], - FAN_DIV_FROM_REG(data->fan_div[nr])) : 0; - return sprintf(buf, "%d\n", value); -} - -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", FAN_DIV_FROM_REG(data->fan_div[nr])); -} -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - FAN_FROM_REG(data->fan_min[nr], - FAN_DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - if (val) { - data->fan_min[nr] = - FAN_TO_REG(val, FAN_DIV_FROM_REG(data->fan_div[nr])); - } else { - data->fan_min[nr] = 0xff; - } - adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - u8 tmp; - int old_div; - int new_min; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - tmp = val == 8 ? 0xc0 : - val == 4 ? 0x80 : - val == 2 ? 0x40 : - val == 1 ? 0x00 : - 0xff; - if (tmp == 0xff) - return -EINVAL; - - mutex_lock(&data->update_lock); - /* Get fresh readings */ - data->fan_div[nr] = adm1031_read_value(client, - ADM1031_REG_FAN_DIV(nr)); - data->fan_min[nr] = adm1031_read_value(client, - ADM1031_REG_FAN_MIN(nr)); - - /* Write the new clock divider and fan min */ - old_div = FAN_DIV_FROM_REG(data->fan_div[nr]); - data->fan_div[nr] = tmp | (0x3f & data->fan_div[nr]); - new_min = data->fan_min[nr] * old_div / val; - data->fan_min[nr] = new_min > 0xff ? 0xff : new_min; - - adm1031_write_value(client, ADM1031_REG_FAN_DIV(nr), - data->fan_div[nr]); - adm1031_write_value(client, ADM1031_REG_FAN_MIN(nr), - data->fan_min[nr]); - - /* Invalidate the cache: fan speed is no longer valid */ - data->valid = 0; - mutex_unlock(&data->update_lock); - return count; -} - -#define fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1) - -fan_offset(1); -fan_offset(2); - - -/* Temps */ -static ssize_t show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - int ext; - ext = nr == 0 ? - ((data->ext_temp[nr] >> 6) & 0x3) * 2 : - (((data->ext_temp[nr] >> ((nr - 1) * 3)) & 7)); - return sprintf(buf, "%d\n", TEMP_FROM_REG_EXT(data->temp[nr], ext)); -} -static ssize_t show_temp_offset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", - TEMP_OFFSET_FROM_REG(data->temp_offset[nr])); -} -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); -} -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); -} -static ssize_t show_temp_crit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit[nr])); -} -static ssize_t set_temp_offset(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - val = SENSORS_LIMIT(val, -15000, 15000); - mutex_lock(&data->update_lock); - data->temp_offset[nr] = TEMP_OFFSET_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_OFFSET(nr), - data->temp_offset[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_MIN(nr), - data->temp_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_MAX(nr), - data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int ret; - - ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - val = SENSORS_LIMIT(val, -55000, nr == 0 ? 127750 : 127875); - mutex_lock(&data->update_lock); - data->temp_crit[nr] = TEMP_TO_REG(val); - adm1031_write_value(client, ADM1031_REG_TEMP_CRIT(nr), - data->temp_crit[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define temp_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \ - show_temp_offset, set_temp_offset, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO | S_IWUSR, \ - show_temp_crit, set_temp_crit, offset - 1) - -temp_reg(1); -temp_reg(2); -temp_reg(3); - -/* Alarms */ -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", data->alarm); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct adm1031_data *data = adm1031_update_device(dev); - return sprintf(buf, "%d\n", (data->alarm >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 14); - -/* Update Interval */ -static const unsigned int update_intervals[] = { - 16000, 8000, 4000, 2000, 1000, 500, 250, 125, -}; - -static ssize_t show_update_interval(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - - return sprintf(buf, "%u\n", data->update_interval); -} - -static ssize_t set_update_interval(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - unsigned long val; - int i, err; - u8 reg; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - /* - * Find the nearest update interval from the table. - * Use it to determine the matching update rate. - */ - for (i = 0; i < ARRAY_SIZE(update_intervals) - 1; i++) { - if (val >= update_intervals[i]) - break; - } - /* if not found, we point to the last entry (lowest update interval) */ - - /* set the new update rate while preserving other settings */ - reg = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); - reg &= ~ADM1031_UPDATE_RATE_MASK; - reg |= i << ADM1031_UPDATE_RATE_SHIFT; - adm1031_write_value(client, ADM1031_REG_FAN_FILTER, reg); - - mutex_lock(&data->update_lock); - data->update_interval = update_intervals[i]; - mutex_unlock(&data->update_lock); - - return count; -} - -static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, - set_update_interval); - -static struct attribute *adm1031_attributes[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_auto_fan1_channel.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - - &sensor_dev_attr_auto_temp1_off.dev_attr.attr, - &sensor_dev_attr_auto_temp1_min.dev_attr.attr, - &sensor_dev_attr_auto_temp1_max.dev_attr.attr, - - &sensor_dev_attr_auto_temp2_off.dev_attr.attr, - &sensor_dev_attr_auto_temp2_min.dev_attr.attr, - &sensor_dev_attr_auto_temp2_max.dev_attr.attr, - - &sensor_dev_attr_auto_fan1_min_pwm.dev_attr.attr, - - &dev_attr_update_interval.attr, - &dev_attr_alarms.attr, - - NULL -}; - -static const struct attribute_group adm1031_group = { - .attrs = adm1031_attributes, -}; - -static struct attribute *adm1031_attributes_opt[] = { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_fault.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_auto_fan2_channel.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_auto_temp3_off.dev_attr.attr, - &sensor_dev_attr_auto_temp3_min.dev_attr.attr, - &sensor_dev_attr_auto_temp3_max.dev_attr.attr, - &sensor_dev_attr_auto_fan2_min_pwm.dev_attr.attr, - NULL -}; - -static const struct attribute_group adm1031_group_opt = { - .attrs = adm1031_attributes_opt, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm1031_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - const char *name; - int id, co; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - id = i2c_smbus_read_byte_data(client, 0x3d); - co = i2c_smbus_read_byte_data(client, 0x3e); - - if (!((id == 0x31 || id == 0x30) && co == 0x41)) - return -ENODEV; - name = (id == 0x30) ? "adm1030" : "adm1031"; - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int adm1031_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1031_data *data; - int err; - - data = kzalloc(sizeof(struct adm1031_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->chip_type = id->driver_data; - mutex_init(&data->update_lock); - - if (data->chip_type == adm1030) - data->chan_select_table = &auto_channel_select_table_adm1030; - else - data->chan_select_table = &auto_channel_select_table_adm1031; - - /* Initialize the ADM1031 chip */ - adm1031_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1031_group); - if (err) - goto exit_free; - - if (data->chip_type == adm1031) { - err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &adm1031_group); - sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); -exit_free: - kfree(data); -exit: - return err; -} - -static int adm1031_remove(struct i2c_client *client) -{ - struct adm1031_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1031_group); - sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); - kfree(data); - return 0; -} - -static void adm1031_init_client(struct i2c_client *client) -{ - unsigned int read_val; - unsigned int mask; - int i; - struct adm1031_data *data = i2c_get_clientdata(client); - - mask = (ADM1031_CONF2_PWM1_ENABLE | ADM1031_CONF2_TACH1_ENABLE); - if (data->chip_type == adm1031) { - mask |= (ADM1031_CONF2_PWM2_ENABLE | - ADM1031_CONF2_TACH2_ENABLE); - } - /* Initialize the ADM1031 chip (enables fan speed reading ) */ - read_val = adm1031_read_value(client, ADM1031_REG_CONF2); - if ((read_val | mask) != read_val) - adm1031_write_value(client, ADM1031_REG_CONF2, read_val | mask); - - read_val = adm1031_read_value(client, ADM1031_REG_CONF1); - if ((read_val | ADM1031_CONF1_MONITOR_ENABLE) != read_val) { - adm1031_write_value(client, ADM1031_REG_CONF1, - read_val | ADM1031_CONF1_MONITOR_ENABLE); - } - - /* Read the chip's update rate */ - mask = ADM1031_UPDATE_RATE_MASK; - read_val = adm1031_read_value(client, ADM1031_REG_FAN_FILTER); - i = (read_val & mask) >> ADM1031_UPDATE_RATE_SHIFT; - /* Save it as update interval */ - data->update_interval = update_intervals[i]; -} - -static struct adm1031_data *adm1031_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - unsigned long next_update; - int chan; - - mutex_lock(&data->update_lock); - - next_update = data->last_updated - + msecs_to_jiffies(data->update_interval); - if (time_after(jiffies, next_update) || !data->valid) { - - dev_dbg(&client->dev, "Starting adm1031 update\n"); - for (chan = 0; - chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { - u8 oldh, newh; - - oldh = - adm1031_read_value(client, ADM1031_REG_TEMP(chan)); - data->ext_temp[chan] = - adm1031_read_value(client, ADM1031_REG_EXT_TEMP); - newh = - adm1031_read_value(client, ADM1031_REG_TEMP(chan)); - if (newh != oldh) { - data->ext_temp[chan] = - adm1031_read_value(client, - ADM1031_REG_EXT_TEMP); -#ifdef DEBUG - oldh = - adm1031_read_value(client, - ADM1031_REG_TEMP(chan)); - - /* oldh is actually newer */ - if (newh != oldh) - dev_warn(&client->dev, - "Remote temperature may be wrong.\n"); -#endif - } - data->temp[chan] = newh; - - data->temp_offset[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_OFFSET(chan)); - data->temp_min[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_MIN(chan)); - data->temp_max[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_MAX(chan)); - data->temp_crit[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_CRIT(chan)); - data->auto_temp[chan] = - adm1031_read_value(client, - ADM1031_REG_AUTO_TEMP(chan)); - - } - - data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); - data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); - - data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) - | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); - if (data->chip_type == adm1030) - data->alarm &= 0xc0ff; - - for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); - chan++) { - data->fan_div[chan] = - adm1031_read_value(client, - ADM1031_REG_FAN_DIV(chan)); - data->fan_min[chan] = - adm1031_read_value(client, - ADM1031_REG_FAN_MIN(chan)); - data->fan[chan] = - adm1031_read_value(client, - ADM1031_REG_FAN_SPEED(chan)); - data->pwm[chan] = - (adm1031_read_value(client, - ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(adm1031_driver); - -MODULE_AUTHOR("Alexandre d'Alton "); -MODULE_DESCRIPTION("ADM1031/ADM1030 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adm9240.c b/ANDROID_3.4.5/drivers/hwmon/adm9240.c deleted file mode 100644 index c3c2865a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adm9240.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - * adm9240.c Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * - * Copyright (C) 1999 Frodo Looijaard - * Philip Edelbrock - * Copyright (C) 2003 Michiel Rook - * Copyright (C) 2005 Grant Coady with valuable - * guidance from Jean Delvare - * - * Driver supports Analog Devices ADM9240 - * Dallas Semiconductor DS1780 - * National Semiconductor LM81 - * - * ADM9240 is the reference, DS1780 and LM81 are register compatibles - * - * Voltage Six inputs are scaled by chip, VID also reported - * Temperature Chip temperature to 0.5'C, maximum and max_hysteris - * Fans 2 fans, low speed alarm, automatic fan clock divider - * Alarms 16-bit map of active alarms - * Analog Out 0..1250 mV output - * - * Chassis Intrusion: clear CI latch with 'echo 0 > intrusion0_alarm' - * - * Test hardware: Intel SE440BX-2 desktop motherboard --Grant - * - * LM81 extended temp reading not implemented - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, - I2C_CLIENT_END }; - -enum chips { adm9240, ds1780, lm81 }; - -/* ADM9240 registers */ -#define ADM9240_REG_MAN_ID 0x3e -#define ADM9240_REG_DIE_REV 0x3f -#define ADM9240_REG_CONFIG 0x40 - -#define ADM9240_REG_IN(nr) (0x20 + (nr)) /* 0..5 */ -#define ADM9240_REG_IN_MAX(nr) (0x2b + (nr) * 2) -#define ADM9240_REG_IN_MIN(nr) (0x2c + (nr) * 2) -#define ADM9240_REG_FAN(nr) (0x28 + (nr)) /* 0..1 */ -#define ADM9240_REG_FAN_MIN(nr) (0x3b + (nr)) -#define ADM9240_REG_INT(nr) (0x41 + (nr)) -#define ADM9240_REG_INT_MASK(nr) (0x43 + (nr)) -#define ADM9240_REG_TEMP 0x27 -#define ADM9240_REG_TEMP_MAX(nr) (0x39 + (nr)) /* 0, 1 = high, hyst */ -#define ADM9240_REG_ANALOG_OUT 0x19 -#define ADM9240_REG_CHASSIS_CLEAR 0x46 -#define ADM9240_REG_VID_FAN_DIV 0x47 -#define ADM9240_REG_I2C_ADDR 0x48 -#define ADM9240_REG_VID4 0x49 -#define ADM9240_REG_TEMP_CONF 0x4b - -/* generalised scaling with integer rounding */ -static inline int SCALE(long val, int mul, int div) -{ - if (val < 0) - return (val * mul - div / 2) / div; - else - return (val * mul + div / 2) / div; -} - -/* adm9240 internally scales voltage measurements */ -static const u16 nom_mv[] = { 2500, 2700, 3300, 5000, 12000, 2700 }; - -static inline unsigned int IN_FROM_REG(u8 reg, int n) -{ - return SCALE(reg, nom_mv[n], 192); -} - -static inline u8 IN_TO_REG(unsigned long val, int n) -{ - return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); -} - -/* temperature range: -40..125, 127 disables temperature alarm */ -static inline s8 TEMP_TO_REG(long val) -{ - return SENSORS_LIMIT(SCALE(val, 1, 1000), -40, 127); -} - -/* two fans, each with low fan speed limit */ -static inline unsigned int FAN_FROM_REG(u8 reg, u8 div) -{ - if (!reg) /* error */ - return -1; - - if (reg == 255) - return 0; - - return SCALE(1350000, 1, reg * div); -} - -/* analog out 0..1250mV */ -static inline u8 AOUT_TO_REG(unsigned long val) -{ - return SENSORS_LIMIT(SCALE(val, 255, 1250), 0, 255); -} - -static inline unsigned int AOUT_FROM_REG(u8 reg) -{ - return SCALE(reg, 1250, 255); -} - -static int adm9240_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm9240_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm9240_init_client(struct i2c_client *client); -static int adm9240_remove(struct i2c_client *client); -static struct adm9240_data *adm9240_update_device(struct device *dev); - -/* driver data */ -static const struct i2c_device_id adm9240_id[] = { - { "adm9240", adm9240 }, - { "ds1780", ds1780 }, - { "lm81", lm81 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm9240_id); - -static struct i2c_driver adm9240_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm9240", - }, - .probe = adm9240_probe, - .remove = adm9240_remove, - .id_table = adm9240_id, - .detect = adm9240_detect, - .address_list = normal_i2c, -}; - -/* per client data */ -struct adm9240_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; - unsigned long last_updated_measure; - unsigned long last_updated_config; - - u8 in[6]; /* ro in0_input */ - u8 in_max[6]; /* rw in0_max */ - u8 in_min[6]; /* rw in0_min */ - u8 fan[2]; /* ro fan1_input */ - u8 fan_min[2]; /* rw fan1_min */ - u8 fan_div[2]; /* rw fan1_div, read-only accessor */ - s16 temp; /* ro temp1_input, 9-bit sign-extended */ - s8 temp_max[2]; /* rw 0 -> temp_max, 1 -> temp_max_hyst */ - u16 alarms; /* ro alarms */ - u8 aout; /* rw aout_output */ - u8 vid; /* ro vid */ - u8 vrm; /* -- vrm set on startup, no accessor */ -}; - -/*** sysfs accessors ***/ - -/* temperature */ -static ssize_t show_temp(struct device *dev, struct device_attribute *dummy, - char *buf) -{ - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", data->temp * 500); /* 9-bit value */ -} - -static ssize_t show_max(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", data->temp_max[attr->index] * 1000); -} - -static ssize_t set_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[attr->index] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, ADM9240_REG_TEMP_MAX(attr->index), - data->temp_max[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_max, set_max, 0); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, - show_max, set_max, 1); - -/* voltage */ -static ssize_t show_in(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index], - attr->index)); -} - -static ssize_t show_in_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index], - attr->index)); -} - -static ssize_t show_in_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index], - attr->index)); -} - -static ssize_t set_in_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[attr->index] = IN_TO_REG(val, attr->index); - i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MIN(attr->index), - data->in_min[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[attr->index] = IN_TO_REG(val, attr->index); - i2c_smbus_write_byte_data(client, ADM9240_REG_IN_MAX(attr->index), - data->in_max[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -#define vin(nr) \ -static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, \ - show_in, NULL, nr); \ -static SENSOR_DEVICE_ATTR(in##nr##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, nr); \ -static SENSOR_DEVICE_ATTR(in##nr##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, nr); - -vin(0); -vin(1); -vin(2); -vin(3); -vin(4); -vin(5); - -/* fans */ -static ssize_t show_fan(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index], - 1 << data->fan_div[attr->index])); -} - -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[attr->index], - 1 << data->fan_div[attr->index])); -} - -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]); -} - -/* write new fan div, callers must hold data->update_lock */ -static void adm9240_write_fan_div(struct i2c_client *client, int nr, - u8 fan_div) -{ - u8 reg, old, shift = (nr + 2) * 2; - - reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV); - old = (reg >> shift) & 3; - reg &= ~(3 << shift); - reg |= (fan_div << shift); - i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg); - dev_dbg(&client->dev, "fan%d clock divider changed from %u " - "to %u\n", nr + 1, 1 << old, 1 << fan_div); -} - -/* - * set fan speed low limit: - * - * - value is zero: disable fan speed low limit alarm - * - * - value is below fan speed measurement range: enable fan speed low - * limit alarm to be asserted while fan speed too slow to measure - * - * - otherwise: select fan clock divider to suit fan speed low limit, - * measurement code may adjust registers to ensure fan speed reading - */ -static ssize_t set_fan_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - int nr = attr->index; - u8 new_div; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - if (!val) { - data->fan_min[nr] = 255; - new_div = data->fan_div[nr]; - - dev_dbg(&client->dev, "fan%u low limit set disabled\n", - nr + 1); - - } else if (val < 1350000 / (8 * 254)) { - new_div = 3; - data->fan_min[nr] = 254; - - dev_dbg(&client->dev, "fan%u low limit set minimum %u\n", - nr + 1, FAN_FROM_REG(254, 1 << new_div)); - - } else { - unsigned int new_min = 1350000 / val; - - new_div = 0; - while (new_min > 192 && new_div < 3) { - new_div++; - new_min /= 2; - } - if (!new_min) /* keep > 0 */ - new_min++; - - data->fan_min[nr] = new_min; - - dev_dbg(&client->dev, "fan%u low limit set fan speed %u\n", - nr + 1, FAN_FROM_REG(new_min, 1 << new_div)); - } - - if (new_div != data->fan_div[nr]) { - data->fan_div[nr] = new_div; - adm9240_write_fan_div(client, nr, new_div); - } - i2c_smbus_write_byte_data(client, ADM9240_REG_FAN_MIN(nr), - data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - return count; -} - -#define fan(nr) \ -static SENSOR_DEVICE_ATTR(fan##nr##_input, S_IRUGO, \ - show_fan, NULL, nr - 1); \ -static SENSOR_DEVICE_ATTR(fan##nr##_div, S_IRUGO, \ - show_fan_div, NULL, nr - 1); \ -static SENSOR_DEVICE_ATTR(fan##nr##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, nr - 1); - -fan(1); -fan(2); - -/* alarms */ -static ssize_t show_alarms(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); - -/* vid */ -static ssize_t show_vid(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -/* analog output */ -static ssize_t show_aout(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct adm9240_data *data = adm9240_update_device(dev); - return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout)); -} - -static ssize_t set_aout(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->aout = AOUT_TO_REG(val); - i2c_smbus_write_byte_data(client, ADM9240_REG_ANALOG_OUT, data->aout); - mutex_unlock(&data->update_lock); - return count; -} -static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); - -/* chassis_clear */ -static ssize_t chassis_clear_legacy(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - dev_warn(dev, "Attribute chassis_clear is deprecated, " - "use intrusion0_alarm instead\n"); - - if (val == 1) { - i2c_smbus_write_byte_data(client, - ADM9240_REG_CHASSIS_CLEAR, 0x80); - dev_dbg(&client->dev, "chassis intrusion latch cleared\n"); - } - return count; -} -static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear_legacy); - -static ssize_t chassis_clear(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) || val != 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - i2c_smbus_write_byte_data(client, ADM9240_REG_CHASSIS_CLEAR, 0x80); - data->valid = 0; /* Force cache refresh */ - mutex_unlock(&data->update_lock); - dev_dbg(&client->dev, "chassis intrusion latch cleared\n"); - - return count; -} -static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm, - chassis_clear, 12); - -static struct attribute *adm9240_attributes[] = { - &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, - &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, - &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, - &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, - &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, - &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, - &dev_attr_temp1_input.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_aout_output.attr, - &dev_attr_chassis_clear.attr, - &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, - &dev_attr_cpu0_vid.attr, - NULL -}; - -static const struct attribute_group adm9240_group = { - .attrs = adm9240_attributes, -}; - - -/*** sensor chip detect and driver install ***/ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adm9240_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - const char *name = ""; - int address = new_client->addr; - u8 man_id, die_rev; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* verify chip: reg address should match i2c address */ - if (i2c_smbus_read_byte_data(new_client, ADM9240_REG_I2C_ADDR) - != address) { - dev_err(&adapter->dev, "detect fail: address match, 0x%02x\n", - address); - return -ENODEV; - } - - /* check known chip manufacturer */ - man_id = i2c_smbus_read_byte_data(new_client, ADM9240_REG_MAN_ID); - if (man_id == 0x23) { - name = "adm9240"; - } else if (man_id == 0xda) { - name = "ds1780"; - } else if (man_id == 0x01) { - name = "lm81"; - } else { - dev_err(&adapter->dev, "detect fail: unknown manuf, 0x%02x\n", - man_id); - return -ENODEV; - } - - /* successful detect, print chip info */ - die_rev = i2c_smbus_read_byte_data(new_client, ADM9240_REG_DIE_REV); - dev_info(&adapter->dev, "found %s revision %u\n", - man_id == 0x23 ? "ADM9240" : - man_id == 0xda ? "DS1780" : "LM81", die_rev); - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int adm9240_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct adm9240_data *data; - int err; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - mutex_init(&data->update_lock); - - adm9240_init_client(new_client); - - /* populate sysfs filesystem */ - err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &adm9240_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int adm9240_remove(struct i2c_client *client) -{ - struct adm9240_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm9240_group); - - kfree(data); - return 0; -} - -static void adm9240_init_client(struct i2c_client *client) -{ - struct adm9240_data *data = i2c_get_clientdata(client); - u8 conf = i2c_smbus_read_byte_data(client, ADM9240_REG_CONFIG); - u8 mode = i2c_smbus_read_byte_data(client, ADM9240_REG_TEMP_CONF) & 3; - - data->vrm = vid_which_vrm(); /* need this to report vid as mV */ - - dev_info(&client->dev, "Using VRM: %d.%d\n", data->vrm / 10, - data->vrm % 10); - - if (conf & 1) { /* measurement cycle running: report state */ - - dev_info(&client->dev, "status: config 0x%02x mode %u\n", - conf, mode); - - } else { /* cold start: open limits before starting chip */ - int i; - - for (i = 0; i < 6; i++) { - i2c_smbus_write_byte_data(client, - ADM9240_REG_IN_MIN(i), 0); - i2c_smbus_write_byte_data(client, - ADM9240_REG_IN_MAX(i), 255); - } - i2c_smbus_write_byte_data(client, - ADM9240_REG_FAN_MIN(0), 255); - i2c_smbus_write_byte_data(client, - ADM9240_REG_FAN_MIN(1), 255); - i2c_smbus_write_byte_data(client, - ADM9240_REG_TEMP_MAX(0), 127); - i2c_smbus_write_byte_data(client, - ADM9240_REG_TEMP_MAX(1), 127); - - /* start measurement cycle */ - i2c_smbus_write_byte_data(client, ADM9240_REG_CONFIG, 1); - - dev_info(&client->dev, "cold start: config was 0x%02x " - "mode %u\n", conf, mode); - } -} - -static struct adm9240_data *adm9240_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - /* minimum measurement cycle: 1.75 seconds */ - if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) - || !data->valid) { - - for (i = 0; i < 6; i++) { /* read voltages */ - data->in[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_IN(i)); - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM9240_REG_INT(0)) | - i2c_smbus_read_byte_data(client, - ADM9240_REG_INT(1)) << 8; - - /* - * read temperature: assume temperature changes less than - * 0.5'C per two measurement cycles thus ignore possible - * but unlikely aliasing error on lsb reading. --Grant - */ - data->temp = ((i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP) << 8) | - i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP_CONF)) / 128; - - for (i = 0; i < 2; i++) { /* read fans */ - data->fan[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_FAN(i)); - - /* adjust fan clock divider on overflow */ - if (data->valid && data->fan[i] == 255 && - data->fan_div[i] < 3) { - - adm9240_write_fan_div(client, i, - ++data->fan_div[i]); - - /* adjust fan_min if active, but not to 0 */ - if (data->fan_min[i] < 255 && - data->fan_min[i] >= 2) - data->fan_min[i] /= 2; - } - } - data->last_updated_measure = jiffies; - } - - /* minimum config reading cycle: 300 seconds */ - if (time_after(jiffies, data->last_updated_config + (HZ * 300)) - || !data->valid) { - - for (i = 0; i < 6; i++) { - data->in_min[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_IN_MIN(i)); - data->in_max[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_IN_MAX(i)); - } - for (i = 0; i < 2; i++) { - data->fan_min[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_FAN_MIN(i)); - } - data->temp_max[0] = i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP_MAX(0)); - data->temp_max[1] = i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP_MAX(1)); - - /* read fan divs and 5-bit VID */ - i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV); - data->fan_div[0] = (i >> 4) & 3; - data->fan_div[1] = (i >> 6) & 3; - data->vid = i & 0x0f; - data->vid |= (i2c_smbus_read_byte_data(client, - ADM9240_REG_VID4) & 1) << 4; - /* read analog out */ - data->aout = i2c_smbus_read_byte_data(client, - ADM9240_REG_ANALOG_OUT); - - data->last_updated_config = jiffies; - data->valid = 1; - } - mutex_unlock(&data->update_lock); - return data; -} - -module_i2c_driver(adm9240_driver); - -MODULE_AUTHOR("Michiel Rook , " - "Grant Coady and others"); -MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ads1015.c b/ANDROID_3.4.5/drivers/hwmon/ads1015.c deleted file mode 100644 index 1958f03e..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ads1015.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC - * (C) Copyright 2010 - * Dirk Eibach, Guntermann & Drunck GmbH - * - * Based on the ads7828 driver by Steve Hardy. - * - * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -/* ADS1015 registers */ -enum { - ADS1015_CONVERSION = 0, - ADS1015_CONFIG = 1, -}; - -/* PGA fullscale voltages in mV */ -static const unsigned int fullscale_table[8] = { - 6144, 4096, 2048, 1024, 512, 256, 256, 256 }; - -/* Data rates in samples per second */ -static const unsigned int data_rate_table[8] = { - 128, 250, 490, 920, 1600, 2400, 3300, 3300 }; - -#define ADS1015_DEFAULT_CHANNELS 0xff -#define ADS1015_DEFAULT_PGA 2 -#define ADS1015_DEFAULT_DATA_RATE 4 - -struct ads1015_data { - struct device *hwmon_dev; - struct mutex update_lock; /* mutex protect updates */ - struct ads1015_channel_data channel_data[ADS1015_CHANNELS]; -}; - -static int ads1015_read_adc(struct i2c_client *client, unsigned int channel) -{ - u16 config; - struct ads1015_data *data = i2c_get_clientdata(client); - unsigned int pga = data->channel_data[channel].pga; - unsigned int data_rate = data->channel_data[channel].data_rate; - unsigned int conversion_time_ms; - int res; - - mutex_lock(&data->update_lock); - - /* get channel parameters */ - res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG); - if (res < 0) - goto err_unlock; - config = res; - conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]); - - /* setup and start single conversion */ - config &= 0x001f; - config |= (1 << 15) | (1 << 8); - config |= (channel & 0x0007) << 12; - config |= (pga & 0x0007) << 9; - config |= (data_rate & 0x0007) << 5; - - res = i2c_smbus_write_word_swapped(client, ADS1015_CONFIG, config); - if (res < 0) - goto err_unlock; - - /* wait until conversion finished */ - msleep(conversion_time_ms); - res = i2c_smbus_read_word_swapped(client, ADS1015_CONFIG); - if (res < 0) - goto err_unlock; - config = res; - if (!(config & (1 << 15))) { - /* conversion not finished in time */ - res = -EIO; - goto err_unlock; - } - - res = i2c_smbus_read_word_swapped(client, ADS1015_CONVERSION); - -err_unlock: - mutex_unlock(&data->update_lock); - return res; -} - -static int ads1015_reg_to_mv(struct i2c_client *client, unsigned int channel, - s16 reg) -{ - struct ads1015_data *data = i2c_get_clientdata(client); - unsigned int pga = data->channel_data[channel].pga; - int fullscale = fullscale_table[pga]; - - return DIV_ROUND_CLOSEST(reg * fullscale, 0x7ff0); -} - -/* sysfs callback function */ -static ssize_t show_in(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - int res; - int index = attr->index; - - res = ads1015_read_adc(client, index); - if (res < 0) - return res; - - return sprintf(buf, "%d\n", ads1015_reg_to_mv(client, index, res)); -} - -static const struct sensor_device_attribute ads1015_in[] = { - SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), -}; - -/* - * Driver interface - */ - -static int ads1015_remove(struct i2c_client *client) -{ - struct ads1015_data *data = i2c_get_clientdata(client); - int k; - - hwmon_device_unregister(data->hwmon_dev); - for (k = 0; k < ADS1015_CHANNELS; ++k) - device_remove_file(&client->dev, &ads1015_in[k].dev_attr); - kfree(data); - return 0; -} - -#ifdef CONFIG_OF -static int ads1015_get_channels_config_of(struct i2c_client *client) -{ - struct ads1015_data *data = i2c_get_clientdata(client); - struct device_node *node; - - if (!client->dev.of_node - || !of_get_next_child(client->dev.of_node, NULL)) - return -EINVAL; - - for_each_child_of_node(client->dev.of_node, node) { - const __be32 *property; - int len; - unsigned int channel; - unsigned int pga = ADS1015_DEFAULT_PGA; - unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE; - - property = of_get_property(node, "reg", &len); - if (!property || len != sizeof(int)) { - dev_err(&client->dev, "invalid reg on %s\n", - node->full_name); - continue; - } - - channel = be32_to_cpup(property); - if (channel > ADS1015_CHANNELS) { - dev_err(&client->dev, - "invalid channel index %d on %s\n", - channel, node->full_name); - continue; - } - - property = of_get_property(node, "ti,gain", &len); - if (property && len == sizeof(int)) { - pga = be32_to_cpup(property); - if (pga > 6) { - dev_err(&client->dev, - "invalid gain on %s\n", - node->full_name); - } - } - - property = of_get_property(node, "ti,datarate", &len); - if (property && len == sizeof(int)) { - data_rate = be32_to_cpup(property); - if (data_rate > 7) { - dev_err(&client->dev, - "invalid data_rate on %s\n", - node->full_name); - } - } - - data->channel_data[channel].enabled = true; - data->channel_data[channel].pga = pga; - data->channel_data[channel].data_rate = data_rate; - } - - return 0; -} -#endif - -static void ads1015_get_channels_config(struct i2c_client *client) -{ - unsigned int k; - struct ads1015_data *data = i2c_get_clientdata(client); - struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev); - - /* prefer platform data */ - if (pdata) { - memcpy(data->channel_data, pdata->channel_data, - sizeof(data->channel_data)); - return; - } - -#ifdef CONFIG_OF - if (!ads1015_get_channels_config_of(client)) - return; -#endif - - /* fallback on default configuration */ - for (k = 0; k < ADS1015_CHANNELS; ++k) { - data->channel_data[k].enabled = true; - data->channel_data[k].pga = ADS1015_DEFAULT_PGA; - data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE; - } -} - -static int ads1015_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ads1015_data *data; - int err; - unsigned int k; - - data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* build sysfs attribute group */ - ads1015_get_channels_config(client); - for (k = 0; k < ADS1015_CHANNELS; ++k) { - if (!data->channel_data[k].enabled) - continue; - err = device_create_file(&client->dev, &ads1015_in[k].dev_attr); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - for (k = 0; k < ADS1015_CHANNELS; ++k) - device_remove_file(&client->dev, &ads1015_in[k].dev_attr); - kfree(data); -exit: - return err; -} - -static const struct i2c_device_id ads1015_id[] = { - { "ads1015", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ads1015_id); - -static struct i2c_driver ads1015_driver = { - .driver = { - .name = "ads1015", - }, - .probe = ads1015_probe, - .remove = ads1015_remove, - .id_table = ads1015_id, -}; - -module_i2c_driver(ads1015_driver); - -MODULE_AUTHOR("Dirk Eibach "); -MODULE_DESCRIPTION("ADS1015 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ads7828.c b/ANDROID_3.4.5/drivers/hwmon/ads7828.c deleted file mode 100644 index bf3fdf49..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ads7828.c +++ /dev/null @@ -1,274 +0,0 @@ -/* - * ads7828.c - lm_sensors driver for ads7828 12-bit 8-channel ADC - * (C) 2007 EADS Astrium - * - * This driver is based on the lm75 and other lm_sensors/hwmon drivers - * - * Written by Steve Hardy - * - * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads7828.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* The ADS7828 registers */ -#define ADS7828_NCH 8 /* 8 channels of 12-bit A-D supported */ -#define ADS7828_CMD_SD_SE 0x80 /* Single ended inputs */ -#define ADS7828_CMD_SD_DIFF 0x00 /* Differential inputs */ -#define ADS7828_CMD_PD0 0x0 /* Power Down between A-D conversions */ -#define ADS7828_CMD_PD1 0x04 /* Internal ref OFF && A-D ON */ -#define ADS7828_CMD_PD2 0x08 /* Internal ref ON && A-D OFF */ -#define ADS7828_CMD_PD3 0x0C /* Internal ref ON && A-D ON */ -#define ADS7828_INT_VREF_MV 2500 /* Internal vref is 2.5V, 2500mV */ - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, - I2C_CLIENT_END }; - -/* Module parameters */ -static bool se_input = 1; /* Default is SE, 0 == diff */ -static bool int_vref = 1; /* Default is internal ref ON */ -static int vref_mv = ADS7828_INT_VREF_MV; /* set if vref != 2.5V */ -module_param(se_input, bool, S_IRUGO); -module_param(int_vref, bool, S_IRUGO); -module_param(vref_mv, int, S_IRUGO); - -/* Global Variables */ -static u8 ads7828_cmd_byte; /* cmd byte without channel bits */ -static unsigned int ads7828_lsb_resol; /* resolution of the ADC sample lsb */ - -/* Each client has this additional data */ -struct ads7828_data { - struct device *hwmon_dev; - struct mutex update_lock; /* mutex protect updates */ - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH 12-bit samples */ -}; - -/* Function declaration - necessary due to function dependencies */ -static int ads7828_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int ads7828_probe(struct i2c_client *client, - const struct i2c_device_id *id); - -static inline u8 channel_cmd_byte(int ch) -{ - /* cmd byte C2,C1,C0 - see datasheet */ - u8 cmd = (((ch>>1) | (ch&0x01)<<2)<<4); - cmd |= ads7828_cmd_byte; - return cmd; -} - -/* Update data for the device (all 8 channels) */ -static struct ads7828_data *ads7828_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ads7828_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - unsigned int ch; - dev_dbg(&client->dev, "Starting ads7828 update\n"); - - for (ch = 0; ch < ADS7828_NCH; ch++) { - u8 cmd = channel_cmd_byte(ch); - data->adc_input[ch] = - i2c_smbus_read_word_swapped(client, cmd); - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* sysfs callback function */ -static ssize_t show_in(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ads7828_data *data = ads7828_update_device(dev); - /* Print value (in mV as specified in sysfs-interface documentation) */ - return sprintf(buf, "%d\n", (data->adc_input[attr->index] * - ads7828_lsb_resol)/1000); -} - -#define in_reg(offset)\ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in,\ - NULL, offset) - -in_reg(0); -in_reg(1); -in_reg(2); -in_reg(3); -in_reg(4); -in_reg(5); -in_reg(6); -in_reg(7); - -static struct attribute *ads7828_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group ads7828_group = { - .attrs = ads7828_attributes, -}; - -static int ads7828_remove(struct i2c_client *client) -{ - struct ads7828_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ads7828_group); - kfree(i2c_get_clientdata(client)); - return 0; -} - -static const struct i2c_device_id ads7828_id[] = { - { "ads7828", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ads7828_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ads7828_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "ads7828", - }, - .probe = ads7828_probe, - .remove = ads7828_remove, - .id_table = ads7828_id, - .detect = ads7828_detect, - .address_list = normal_i2c, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int ads7828_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int ch; - - /* Check we have a valid client */ - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -ENODEV; - - /* - * Now, we do the remaining detection. There is no identification - * dedicated register so attempt to sanity check using knowledge of - * the chip - * - Read from the 8 channel addresses - * - Check the top 4 bits of each result are not set (12 data bits) - */ - for (ch = 0; ch < ADS7828_NCH; ch++) { - u16 in_data; - u8 cmd = channel_cmd_byte(ch); - in_data = i2c_smbus_read_word_swapped(client, cmd); - if (in_data & 0xF000) { - pr_debug("%s : Doesn't look like an ads7828 device\n", - __func__); - return -ENODEV; - } - } - - strlcpy(info->type, "ads7828", I2C_NAME_SIZE); - - return 0; -} - -static int ads7828_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ads7828_data *data; - int err; - - data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &ads7828_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &ads7828_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int __init sensors_ads7828_init(void) -{ - /* Initialize the command byte according to module parameters */ - ads7828_cmd_byte = se_input ? - ADS7828_CMD_SD_SE : ADS7828_CMD_SD_DIFF; - ads7828_cmd_byte |= int_vref ? - ADS7828_CMD_PD3 : ADS7828_CMD_PD1; - - /* Calculate the LSB resolution */ - ads7828_lsb_resol = (vref_mv*1000)/4096; - - return i2c_add_driver(&ads7828_driver); -} - -static void __exit sensors_ads7828_exit(void) -{ - i2c_del_driver(&ads7828_driver); -} - -MODULE_AUTHOR("Steve Hardy "); -MODULE_DESCRIPTION("ADS7828 driver"); -MODULE_LICENSE("GPL"); - -module_init(sensors_ads7828_init); -module_exit(sensors_ads7828_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/ads7871.c b/ANDROID_3.4.5/drivers/hwmon/ads7871.c deleted file mode 100644 index e65c6e45..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ads7871.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * ads7871 - driver for TI ADS7871 A/D converter - * - * Copyright (c) 2010 Paul Thomas - * - * 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. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 or - * later as publishhed by the Free Software Foundation. - * - * You need to have something like this in struct spi_board_info - * { - * .modalias = "ads7871", - * .max_speed_hz = 2*1000*1000, - * .chip_select = 0, - * .bus_num = 1, - * }, - */ - -/*From figure 18 in the datasheet*/ -/*Register addresses*/ -#define REG_LS_BYTE 0 /*A/D Output Data, LS Byte*/ -#define REG_MS_BYTE 1 /*A/D Output Data, MS Byte*/ -#define REG_PGA_VALID 2 /*PGA Valid Register*/ -#define REG_AD_CONTROL 3 /*A/D Control Register*/ -#define REG_GAIN_MUX 4 /*Gain/Mux Register*/ -#define REG_IO_STATE 5 /*Digital I/O State Register*/ -#define REG_IO_CONTROL 6 /*Digital I/O Control Register*/ -#define REG_OSC_CONTROL 7 /*Rev/Oscillator Control Register*/ -#define REG_SER_CONTROL 24 /*Serial Interface Control Register*/ -#define REG_ID 31 /*ID Register*/ - -/* - * From figure 17 in the datasheet - * These bits get ORed with the address to form - * the instruction byte - */ -/*Instruction Bit masks*/ -#define INST_MODE_bm (1<<7) -#define INST_READ_bm (1<<6) -#define INST_16BIT_bm (1<<5) - -/*From figure 18 in the datasheet*/ -/*bit masks for Rev/Oscillator Control Register*/ -#define MUX_CNV_bv 7 -#define MUX_CNV_bm (1< -#include -#include -#include -#include -#include -#include -#include - -#define DEVICE_NAME "ads7871" - -struct ads7871_data { - struct device *hwmon_dev; - struct mutex update_lock; -}; - -static int ads7871_read_reg8(struct spi_device *spi, int reg) -{ - int ret; - reg = reg | INST_READ_bm; - ret = spi_w8r8(spi, reg); - return ret; -} - -static int ads7871_read_reg16(struct spi_device *spi, int reg) -{ - int ret; - reg = reg | INST_READ_bm | INST_16BIT_bm; - ret = spi_w8r16(spi, reg); - return ret; -} - -static int ads7871_write_reg8(struct spi_device *spi, int reg, u8 val) -{ - u8 tmp[2] = {reg, val}; - return spi_write(spi, tmp, sizeof(tmp)); -} - -static ssize_t show_voltage(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int ret, val, i = 0; - uint8_t channel, mux_cnv; - - channel = attr->index; - /* - * TODO: add support for conversions - * other than single ended with a gain of 1 - */ - /*MUX_M3_bm forces single ended*/ - /*This is also where the gain of the PGA would be set*/ - ads7871_write_reg8(spi, REG_GAIN_MUX, - (MUX_CNV_bm | MUX_M3_bm | channel)); - - ret = ads7871_read_reg8(spi, REG_GAIN_MUX); - mux_cnv = ((ret & MUX_CNV_bm)>>MUX_CNV_bv); - /* - * on 400MHz arm9 platform the conversion - * is already done when we do this test - */ - while ((i < 2) && mux_cnv) { - i++; - ret = ads7871_read_reg8(spi, REG_GAIN_MUX); - mux_cnv = ((ret & MUX_CNV_bm)>>MUX_CNV_bv); - msleep_interruptible(1); - } - - if (mux_cnv == 0) { - val = ads7871_read_reg16(spi, REG_LS_BYTE); - /*result in volts*10000 = (val/8192)*2.5*10000*/ - val = ((val>>2) * 25000) / 8192; - return sprintf(buf, "%d\n", val); - } else { - return -1; - } -} - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7); - -static struct attribute *ads7871_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group ads7871_group = { - .attrs = ads7871_attributes, -}; - -static int __devinit ads7871_probe(struct spi_device *spi) -{ - int ret, err; - uint8_t val; - struct ads7871_data *pdata; - - dev_dbg(&spi->dev, "probe\n"); - - /* Configure the SPI bus */ - spi->mode = (SPI_MODE_0); - spi->bits_per_word = 8; - spi_setup(spi); - - ads7871_write_reg8(spi, REG_SER_CONTROL, 0); - ads7871_write_reg8(spi, REG_AD_CONTROL, 0); - - val = (OSC_OSCR_bm | OSC_OSCE_bm | OSC_REFE_bm | OSC_BUFE_bm); - ads7871_write_reg8(spi, REG_OSC_CONTROL, val); - ret = ads7871_read_reg8(spi, REG_OSC_CONTROL); - - dev_dbg(&spi->dev, "REG_OSC_CONTROL write:%x, read:%x\n", val, ret); - /* - * because there is no other error checking on an SPI bus - * we need to make sure we really have a chip - */ - if (val != ret) { - err = -ENODEV; - goto exit; - } - - pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL); - if (!pdata) { - err = -ENOMEM; - goto exit; - } - - err = sysfs_create_group(&spi->dev.kobj, &ads7871_group); - if (err < 0) - goto error_free; - - spi_set_drvdata(spi, pdata); - - pdata->hwmon_dev = hwmon_device_register(&spi->dev); - if (IS_ERR(pdata->hwmon_dev)) { - err = PTR_ERR(pdata->hwmon_dev); - goto error_remove; - } - - return 0; - -error_remove: - sysfs_remove_group(&spi->dev.kobj, &ads7871_group); -error_free: - kfree(pdata); -exit: - return err; -} - -static int __devexit ads7871_remove(struct spi_device *spi) -{ - struct ads7871_data *pdata = spi_get_drvdata(spi); - - hwmon_device_unregister(pdata->hwmon_dev); - sysfs_remove_group(&spi->dev.kobj, &ads7871_group); - kfree(pdata); - return 0; -} - -static struct spi_driver ads7871_driver = { - .driver = { - .name = DEVICE_NAME, - .owner = THIS_MODULE, - }, - - .probe = ads7871_probe, - .remove = __devexit_p(ads7871_remove), -}; - -module_spi_driver(ads7871_driver); - -MODULE_AUTHOR("Paul Thomas "); -MODULE_DESCRIPTION("TI ADS7871 A/D driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adt7411.c b/ANDROID_3.4.5/drivers/hwmon/adt7411.c deleted file mode 100644 index 71bacc56..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adt7411.c +++ /dev/null @@ -1,356 +0,0 @@ -/* - * Driver for the ADT7411 (I2C/SPI 8 channel 10 bit ADC & temperature-sensor) - * - * Copyright (C) 2008, 2010 Pengutronix - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * TODO: SPI, support for external temperature sensor - * use power-down mode for suspend?, interrupt handling? - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ADT7411_REG_INT_TEMP_VDD_LSB 0x03 -#define ADT7411_REG_EXT_TEMP_AIN14_LSB 0x04 -#define ADT7411_REG_VDD_MSB 0x06 -#define ADT7411_REG_INT_TEMP_MSB 0x07 -#define ADT7411_REG_EXT_TEMP_AIN1_MSB 0x08 - -#define ADT7411_REG_CFG1 0x18 -#define ADT7411_CFG1_START_MONITOR (1 << 0) - -#define ADT7411_REG_CFG2 0x19 -#define ADT7411_CFG2_DISABLE_AVG (1 << 5) - -#define ADT7411_REG_CFG3 0x1a -#define ADT7411_CFG3_ADC_CLK_225 (1 << 0) -#define ADT7411_CFG3_REF_VDD (1 << 4) - -#define ADT7411_REG_DEVICE_ID 0x4d -#define ADT7411_REG_MANUFACTURER_ID 0x4e - -#define ADT7411_DEVICE_ID 0x2 -#define ADT7411_MANUFACTURER_ID 0x41 - -static const unsigned short normal_i2c[] = { 0x48, 0x4a, 0x4b, I2C_CLIENT_END }; - -struct adt7411_data { - struct mutex device_lock; /* for "atomic" device accesses */ - struct mutex update_lock; - unsigned long next_update; - int vref_cached; - struct device *hwmon_dev; -}; - -/* - * When reading a register containing (up to 4) lsb, all associated - * msb-registers get locked by the hardware. After _one_ of those msb is read, - * _all_ are unlocked. In order to use this locking correctly, reading lsb/msb - * is protected here with a mutex, too. - */ -static int adt7411_read_10_bit(struct i2c_client *client, u8 lsb_reg, - u8 msb_reg, u8 lsb_shift) -{ - struct adt7411_data *data = i2c_get_clientdata(client); - int val, tmp; - - mutex_lock(&data->device_lock); - - val = i2c_smbus_read_byte_data(client, lsb_reg); - if (val < 0) - goto exit_unlock; - - tmp = (val >> lsb_shift) & 3; - val = i2c_smbus_read_byte_data(client, msb_reg); - - if (val >= 0) - val = (val << 2) | tmp; - - exit_unlock: - mutex_unlock(&data->device_lock); - - return val; -} - -static int adt7411_modify_bit(struct i2c_client *client, u8 reg, u8 bit, - bool flag) -{ - struct adt7411_data *data = i2c_get_clientdata(client); - int ret, val; - - mutex_lock(&data->device_lock); - - ret = i2c_smbus_read_byte_data(client, reg); - if (ret < 0) - goto exit_unlock; - - if (flag) - val = ret | bit; - else - val = ret & ~bit; - - ret = i2c_smbus_write_byte_data(client, reg, val); - - exit_unlock: - mutex_unlock(&data->device_lock); - return ret; -} - -static ssize_t adt7411_show_vdd(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, - ADT7411_REG_VDD_MSB, 2); - - return ret < 0 ? ret : sprintf(buf, "%u\n", ret * 7000 / 1024); -} - -static ssize_t adt7411_show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, - ADT7411_REG_INT_TEMP_MSB, 0); - - if (val < 0) - return val; - - val = val & 0x200 ? val - 0x400 : val; /* 10 bit signed */ - - return sprintf(buf, "%d\n", val * 250); -} - -static ssize_t adt7411_show_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adt7411_data *data = i2c_get_clientdata(client); - int val; - u8 lsb_reg, lsb_shift; - - mutex_lock(&data->update_lock); - if (time_after_eq(jiffies, data->next_update)) { - val = i2c_smbus_read_byte_data(client, ADT7411_REG_CFG3); - if (val < 0) - goto exit_unlock; - - if (val & ADT7411_CFG3_REF_VDD) { - val = adt7411_read_10_bit(client, - ADT7411_REG_INT_TEMP_VDD_LSB, - ADT7411_REG_VDD_MSB, 2); - if (val < 0) - goto exit_unlock; - - data->vref_cached = val * 7000 / 1024; - } else { - data->vref_cached = 2250; - } - - data->next_update = jiffies + HZ; - } - - lsb_reg = ADT7411_REG_EXT_TEMP_AIN14_LSB + (nr >> 2); - lsb_shift = 2 * (nr & 0x03); - val = adt7411_read_10_bit(client, lsb_reg, - ADT7411_REG_EXT_TEMP_AIN1_MSB + nr, lsb_shift); - if (val < 0) - goto exit_unlock; - - val = sprintf(buf, "%u\n", val * data->vref_cached / 1024); - exit_unlock: - mutex_unlock(&data->update_lock); - return val; -} - -static ssize_t adt7411_show_bit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - int ret = i2c_smbus_read_byte_data(client, attr2->index); - - return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr)); -} - -static ssize_t adt7411_set_bit(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7411_data *data = i2c_get_clientdata(client); - int ret; - unsigned long flag; - - ret = kstrtoul(buf, 0, &flag); - if (ret || flag > 1) - return -EINVAL; - - ret = adt7411_modify_bit(client, s_attr2->index, s_attr2->nr, flag); - - /* force update */ - mutex_lock(&data->update_lock); - data->next_update = jiffies; - mutex_unlock(&data->update_lock); - - return ret < 0 ? ret : count; -} - -#define ADT7411_BIT_ATTR(__name, __reg, __bit) \ - SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \ - adt7411_set_bit, __bit, __reg) - -static DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL); -static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, adt7411_show_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, adt7411_show_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, adt7411_show_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, adt7411_show_input, NULL, 5); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, adt7411_show_input, NULL, 6); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, adt7411_show_input, NULL, 7); -static ADT7411_BIT_ATTR(no_average, ADT7411_REG_CFG2, ADT7411_CFG2_DISABLE_AVG); -static ADT7411_BIT_ATTR(fast_sampling, ADT7411_REG_CFG3, ADT7411_CFG3_ADC_CLK_225); -static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD); - -static struct attribute *adt7411_attrs[] = { - &dev_attr_temp1_input.attr, - &dev_attr_in0_input.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_no_average.dev_attr.attr, - &sensor_dev_attr_fast_sampling.dev_attr.attr, - &sensor_dev_attr_adc_ref_vdd.dev_attr.attr, - NULL -}; - -static const struct attribute_group adt7411_attr_grp = { - .attrs = adt7411_attrs, -}; - -static int adt7411_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - int val; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - val = i2c_smbus_read_byte_data(client, ADT7411_REG_MANUFACTURER_ID); - if (val < 0 || val != ADT7411_MANUFACTURER_ID) { - dev_dbg(&client->dev, "Wrong manufacturer ID. Got %d, " - "expected %d\n", val, ADT7411_MANUFACTURER_ID); - return -ENODEV; - } - - val = i2c_smbus_read_byte_data(client, ADT7411_REG_DEVICE_ID); - if (val < 0 || val != ADT7411_DEVICE_ID) { - dev_dbg(&client->dev, "Wrong device ID. Got %d, " - "expected %d\n", val, ADT7411_DEVICE_ID); - return -ENODEV; - } - - strlcpy(info->type, "adt7411", I2C_NAME_SIZE); - - return 0; -} - -static int __devinit adt7411_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt7411_data *data; - int ret; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->device_lock); - mutex_init(&data->update_lock); - - ret = adt7411_modify_bit(client, ADT7411_REG_CFG1, - ADT7411_CFG1_START_MONITOR, 1); - if (ret < 0) - goto exit_free; - - /* force update on first occasion */ - data->next_update = jiffies; - - ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp); - if (ret) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "successfully registered\n"); - - return 0; - - exit_remove: - sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - exit_free: - kfree(data); - return ret; -} - -static int __devexit adt7411_remove(struct i2c_client *client) -{ - struct adt7411_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - kfree(data); - return 0; -} - -static const struct i2c_device_id adt7411_id[] = { - { "adt7411", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7411_id); - -static struct i2c_driver adt7411_driver = { - .driver = { - .name = "adt7411", - }, - .probe = adt7411_probe, - .remove = __devexit_p(adt7411_remove), - .id_table = adt7411_id, - .detect = adt7411_detect, - .address_list = normal_i2c, - .class = I2C_CLASS_HWMON, -}; - -module_i2c_driver(adt7411_driver); - -MODULE_AUTHOR("Sascha Hauer and " - "Wolfram Sang "); -MODULE_DESCRIPTION("ADT7411 driver"); -MODULE_LICENSE("GPL v2"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adt7462.c b/ANDROID_3.4.5/drivers/hwmon/adt7462.c deleted file mode 100644 index 339269f7..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adt7462.c +++ /dev/null @@ -1,1981 +0,0 @@ -/* - * A hwmon driver for the Analog Devices ADT7462 - * Copyright (C) 2008 IBM - * - * Author: Darrick J. Wong - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; - -/* ADT7462 registers */ -#define ADT7462_REG_DEVICE 0x3D -#define ADT7462_REG_VENDOR 0x3E -#define ADT7462_REG_REVISION 0x3F - -#define ADT7462_REG_MIN_TEMP_BASE_ADDR 0x44 -#define ADT7462_REG_MIN_TEMP_MAX_ADDR 0x47 -#define ADT7462_REG_MAX_TEMP_BASE_ADDR 0x48 -#define ADT7462_REG_MAX_TEMP_MAX_ADDR 0x4B -#define ADT7462_REG_TEMP_BASE_ADDR 0x88 -#define ADT7462_REG_TEMP_MAX_ADDR 0x8F - -#define ADT7462_REG_FAN_BASE_ADDR 0x98 -#define ADT7462_REG_FAN_MAX_ADDR 0x9F -#define ADT7462_REG_FAN2_BASE_ADDR 0xA2 -#define ADT7462_REG_FAN2_MAX_ADDR 0xA9 -#define ADT7462_REG_FAN_ENABLE 0x07 -#define ADT7462_REG_FAN_MIN_BASE_ADDR 0x78 -#define ADT7462_REG_FAN_MIN_MAX_ADDR 0x7F - -#define ADT7462_REG_CFG2 0x02 -#define ADT7462_FSPD_MASK 0x20 - -#define ADT7462_REG_PWM_BASE_ADDR 0xAA -#define ADT7462_REG_PWM_MAX_ADDR 0xAD -#define ADT7462_REG_PWM_MIN_BASE_ADDR 0x28 -#define ADT7462_REG_PWM_MIN_MAX_ADDR 0x2B -#define ADT7462_REG_PWM_MAX 0x2C -#define ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR 0x5C -#define ADT7462_REG_PWM_TEMP_MIN_MAX_ADDR 0x5F -#define ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR 0x60 -#define ADT7462_REG_PWM_TEMP_RANGE_MAX_ADDR 0x63 -#define ADT7462_PWM_HYST_MASK 0x0F -#define ADT7462_PWM_RANGE_MASK 0xF0 -#define ADT7462_PWM_RANGE_SHIFT 4 -#define ADT7462_REG_PWM_CFG_BASE_ADDR 0x21 -#define ADT7462_REG_PWM_CFG_MAX_ADDR 0x24 -#define ADT7462_PWM_CHANNEL_MASK 0xE0 -#define ADT7462_PWM_CHANNEL_SHIFT 5 - -#define ADT7462_REG_PIN_CFG_BASE_ADDR 0x10 -#define ADT7462_REG_PIN_CFG_MAX_ADDR 0x13 -#define ADT7462_PIN7_INPUT 0x01 /* cfg0 */ -#define ADT7462_DIODE3_INPUT 0x20 -#define ADT7462_DIODE1_INPUT 0x40 -#define ADT7462_VID_INPUT 0x80 -#define ADT7462_PIN22_INPUT 0x04 /* cfg1 */ -#define ADT7462_PIN21_INPUT 0x08 -#define ADT7462_PIN19_INPUT 0x10 -#define ADT7462_PIN15_INPUT 0x20 -#define ADT7462_PIN13_INPUT 0x40 -#define ADT7462_PIN8_INPUT 0x80 -#define ADT7462_PIN23_MASK 0x03 -#define ADT7462_PIN23_SHIFT 0 -#define ADT7462_PIN26_MASK 0x0C /* cfg2 */ -#define ADT7462_PIN26_SHIFT 2 -#define ADT7462_PIN25_MASK 0x30 -#define ADT7462_PIN25_SHIFT 4 -#define ADT7462_PIN24_MASK 0xC0 -#define ADT7462_PIN24_SHIFT 6 -#define ADT7462_PIN26_VOLT_INPUT 0x08 -#define ADT7462_PIN25_VOLT_INPUT 0x20 -#define ADT7462_PIN28_SHIFT 4 /* cfg3 */ -#define ADT7462_PIN28_VOLT 0x5 - -#define ADT7462_REG_ALARM1 0xB8 -#define ADT7462_LT_ALARM 0x02 -#define ADT7462_R1T_ALARM 0x04 -#define ADT7462_R2T_ALARM 0x08 -#define ADT7462_R3T_ALARM 0x10 -#define ADT7462_REG_ALARM2 0xBB -#define ADT7462_V0_ALARM 0x01 -#define ADT7462_V1_ALARM 0x02 -#define ADT7462_V2_ALARM 0x04 -#define ADT7462_V3_ALARM 0x08 -#define ADT7462_V4_ALARM 0x10 -#define ADT7462_V5_ALARM 0x20 -#define ADT7462_V6_ALARM 0x40 -#define ADT7462_V7_ALARM 0x80 -#define ADT7462_REG_ALARM3 0xBC -#define ADT7462_V8_ALARM 0x08 -#define ADT7462_V9_ALARM 0x10 -#define ADT7462_V10_ALARM 0x20 -#define ADT7462_V11_ALARM 0x40 -#define ADT7462_V12_ALARM 0x80 -#define ADT7462_REG_ALARM4 0xBD -#define ADT7462_F0_ALARM 0x01 -#define ADT7462_F1_ALARM 0x02 -#define ADT7462_F2_ALARM 0x04 -#define ADT7462_F3_ALARM 0x08 -#define ADT7462_F4_ALARM 0x10 -#define ADT7462_F5_ALARM 0x20 -#define ADT7462_F6_ALARM 0x40 -#define ADT7462_F7_ALARM 0x80 -#define ADT7462_ALARM1 0x0000 -#define ADT7462_ALARM2 0x0100 -#define ADT7462_ALARM3 0x0200 -#define ADT7462_ALARM4 0x0300 -#define ADT7462_ALARM_REG_SHIFT 8 -#define ADT7462_ALARM_FLAG_MASK 0x0F - -#define ADT7462_TEMP_COUNT 4 -#define ADT7462_TEMP_REG(x) (ADT7462_REG_TEMP_BASE_ADDR + ((x) * 2)) -#define ADT7462_TEMP_MIN_REG(x) (ADT7462_REG_MIN_TEMP_BASE_ADDR + (x)) -#define ADT7462_TEMP_MAX_REG(x) (ADT7462_REG_MAX_TEMP_BASE_ADDR + (x)) -#define TEMP_FRAC_OFFSET 6 - -#define ADT7462_FAN_COUNT 8 -#define ADT7462_REG_FAN_MIN(x) (ADT7462_REG_FAN_MIN_BASE_ADDR + (x)) - -#define ADT7462_PWM_COUNT 4 -#define ADT7462_REG_PWM(x) (ADT7462_REG_PWM_BASE_ADDR + (x)) -#define ADT7462_REG_PWM_MIN(x) (ADT7462_REG_PWM_MIN_BASE_ADDR + (x)) -#define ADT7462_REG_PWM_TMIN(x) \ - (ADT7462_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) -#define ADT7462_REG_PWM_TRANGE(x) \ - (ADT7462_REG_PWM_TEMP_RANGE_BASE_ADDR + (x)) - -#define ADT7462_PIN_CFG_REG_COUNT 4 -#define ADT7462_REG_PIN_CFG(x) (ADT7462_REG_PIN_CFG_BASE_ADDR + (x)) -#define ADT7462_REG_PWM_CFG(x) (ADT7462_REG_PWM_CFG_BASE_ADDR + (x)) - -#define ADT7462_ALARM_REG_COUNT 4 - -/* - * The chip can measure 13 different voltage sources: - * - * 1. +12V1 (pin 7) - * 2. Vccp1/+2.5V/+1.8V/+1.5V (pin 23) - * 3. +12V3 (pin 22) - * 4. +5V (pin 21) - * 5. +1.25V/+0.9V (pin 19) - * 6. +2.5V/+1.8V (pin 15) - * 7. +3.3v (pin 13) - * 8. +12V2 (pin 8) - * 9. Vbatt/FSB_Vtt (pin 26) - * A. +3.3V/+1.2V1 (pin 25) - * B. Vccp2/+2.5V/+1.8V/+1.5V (pin 24) - * C. +1.5V ICH (only if BOTH pin 28/29 are set to +1.5V) - * D. +1.5V 3GPIO (only if BOTH pin 28/29 are set to +1.5V) - * - * Each of these 13 has a factor to convert raw to voltage. Even better, - * the pins can be connected to other sensors (tach/gpio/hot/etc), which - * makes the bookkeeping tricky. - * - * Some, but not all, of these voltages have low/high limits. - */ -#define ADT7462_VOLT_COUNT 13 - -#define ADT7462_VENDOR 0x41 -#define ADT7462_DEVICE 0x62 -/* datasheet only mentions a revision 4 */ -#define ADT7462_REVISION 0x04 - -/* How often do we reread sensors values? (In jiffies) */ -#define SENSOR_REFRESH_INTERVAL (2 * HZ) - -/* How often do we reread sensor limit values? (In jiffies) */ -#define LIMIT_REFRESH_INTERVAL (60 * HZ) - -/* datasheet says to divide this number by the fan reading to get fan rpm */ -#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) -#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM -#define FAN_PERIOD_INVALID 65535 -#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) - -#define MASK_AND_SHIFT(value, prefix) \ - (((value) & prefix##_MASK) >> prefix##_SHIFT) - -struct adt7462_data { - struct device *hwmon_dev; - struct attribute_group attrs; - struct mutex lock; - char sensors_valid; - char limits_valid; - unsigned long sensors_last_updated; /* In jiffies */ - unsigned long limits_last_updated; /* In jiffies */ - - u8 temp[ADT7462_TEMP_COUNT]; - /* bits 6-7 are quarter pieces of temp */ - u8 temp_frac[ADT7462_TEMP_COUNT]; - u8 temp_min[ADT7462_TEMP_COUNT]; - u8 temp_max[ADT7462_TEMP_COUNT]; - u16 fan[ADT7462_FAN_COUNT]; - u8 fan_enabled; - u8 fan_min[ADT7462_FAN_COUNT]; - u8 cfg2; - u8 pwm[ADT7462_PWM_COUNT]; - u8 pin_cfg[ADT7462_PIN_CFG_REG_COUNT]; - u8 voltages[ADT7462_VOLT_COUNT]; - u8 volt_max[ADT7462_VOLT_COUNT]; - u8 volt_min[ADT7462_VOLT_COUNT]; - u8 pwm_min[ADT7462_PWM_COUNT]; - u8 pwm_tmin[ADT7462_PWM_COUNT]; - u8 pwm_trange[ADT7462_PWM_COUNT]; - u8 pwm_max; /* only one per chip */ - u8 pwm_cfg[ADT7462_PWM_COUNT]; - u8 alarms[ADT7462_ALARM_REG_COUNT]; -}; - -static int adt7462_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adt7462_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adt7462_remove(struct i2c_client *client); - -static const struct i2c_device_id adt7462_id[] = { - { "adt7462", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7462_id); - -static struct i2c_driver adt7462_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adt7462", - }, - .probe = adt7462_probe, - .remove = adt7462_remove, - .id_table = adt7462_id, - .detect = adt7462_detect, - .address_list = normal_i2c, -}; - -/* - * 16-bit registers on the ADT7462 are low-byte first. The data sheet says - * that the low byte must be read before the high byte. - */ -static inline int adt7462_read_word_data(struct i2c_client *client, u8 reg) -{ - u16 foo; - foo = i2c_smbus_read_byte_data(client, reg); - foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); - return foo; -} - -/* For some reason these registers are not contiguous. */ -static int ADT7462_REG_FAN(int fan) -{ - if (fan < 4) - return ADT7462_REG_FAN_BASE_ADDR + (2 * fan); - return ADT7462_REG_FAN2_BASE_ADDR + (2 * (fan - 4)); -} - -/* Voltage registers are scattered everywhere */ -static int ADT7462_REG_VOLT_MAX(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) - return 0x7C; - break; - case 1: - return 0x69; - case 2: - if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) - return 0x7F; - break; - case 3: - if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) - return 0x7E; - break; - case 4: - if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) - return 0x4B; - break; - case 5: - if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) - return 0x49; - break; - case 6: - if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) - return 0x68; - break; - case 7: - if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) - return 0x7D; - break; - case 8: - if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) - return 0x6C; - break; - case 9: - if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) - return 0x6B; - break; - case 10: - return 0x6A; - case 11: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 0x50; - break; - case 12: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 0x4C; - break; - } - return -ENODEV; -} - -static int ADT7462_REG_VOLT_MIN(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) - return 0x6D; - break; - case 1: - return 0x72; - case 2: - if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) - return 0x6F; - break; - case 3: - if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) - return 0x71; - break; - case 4: - if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) - return 0x47; - break; - case 5: - if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) - return 0x45; - break; - case 6: - if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) - return 0x70; - break; - case 7: - if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) - return 0x6E; - break; - case 8: - if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) - return 0x75; - break; - case 9: - if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) - return 0x74; - break; - case 10: - return 0x73; - case 11: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 0x76; - break; - case 12: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 0x77; - break; - } - return -ENODEV; -} - -static int ADT7462_REG_VOLT(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) - return 0xA3; - break; - case 1: - return 0x90; - case 2: - if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) - return 0xA9; - break; - case 3: - if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) - return 0xA7; - break; - case 4: - if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) - return 0x8F; - break; - case 5: - if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) - return 0x8B; - break; - case 6: - if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) - return 0x96; - break; - case 7: - if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) - return 0xA5; - break; - case 8: - if (!(data->pin_cfg[2] & ADT7462_PIN26_VOLT_INPUT)) - return 0x93; - break; - case 9: - if (!(data->pin_cfg[2] & ADT7462_PIN25_VOLT_INPUT)) - return 0x92; - break; - case 10: - return 0x91; - case 11: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 0x94; - break; - case 12: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 0x95; - break; - } - return -ENODEV; -} - -/* Provide labels for sysfs */ -static const char *voltage_label(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) - return "+12V1"; - break; - case 1: - switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { - case 0: - return "Vccp1"; - case 1: - return "+2.5V"; - case 2: - return "+1.8V"; - case 3: - return "+1.5V"; - } - case 2: - if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) - return "+12V3"; - break; - case 3: - if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) - return "+5V"; - break; - case 4: - if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { - if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) - return "+0.9V"; - return "+1.25V"; - } - break; - case 5: - if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { - if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) - return "+1.8V"; - return "+2.5V"; - } - break; - case 6: - if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) - return "+3.3V"; - break; - case 7: - if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) - return "+12V2"; - break; - case 8: - switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { - case 0: - return "Vbatt"; - case 1: - return "FSB_Vtt"; - } - break; - case 9: - switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { - case 0: - return "+3.3V"; - case 1: - return "+1.2V1"; - } - break; - case 10: - switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { - case 0: - return "Vccp2"; - case 1: - return "+2.5V"; - case 2: - return "+1.8V"; - case 3: - return "+1.5"; - } - case 11: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return "+1.5V ICH"; - break; - case 12: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return "+1.5V 3GPIO"; - break; - } - return "N/A"; -} - -/* Multipliers are actually in uV, not mV. */ -static int voltage_multiplier(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - if (!(data->pin_cfg[0] & ADT7462_PIN7_INPUT)) - return 62500; - break; - case 1: - switch (MASK_AND_SHIFT(data->pin_cfg[1], ADT7462_PIN23)) { - case 0: - if (data->pin_cfg[0] & ADT7462_VID_INPUT) - return 12500; - return 6250; - case 1: - return 13000; - case 2: - return 9400; - case 3: - return 7800; - } - case 2: - if (!(data->pin_cfg[1] & ADT7462_PIN22_INPUT)) - return 62500; - break; - case 3: - if (!(data->pin_cfg[1] & ADT7462_PIN21_INPUT)) - return 26000; - break; - case 4: - if (!(data->pin_cfg[0] & ADT7462_DIODE3_INPUT)) { - if (data->pin_cfg[1] & ADT7462_PIN19_INPUT) - return 4690; - return 6500; - } - break; - case 5: - if (!(data->pin_cfg[0] & ADT7462_DIODE1_INPUT)) { - if (data->pin_cfg[1] & ADT7462_PIN15_INPUT) - return 9400; - return 13000; - } - break; - case 6: - if (!(data->pin_cfg[1] & ADT7462_PIN13_INPUT)) - return 17200; - break; - case 7: - if (!(data->pin_cfg[1] & ADT7462_PIN8_INPUT)) - return 62500; - break; - case 8: - switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN26)) { - case 0: - return 15600; - case 1: - return 6250; - } - break; - case 9: - switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN25)) { - case 0: - return 17200; - case 1: - return 6250; - } - break; - case 10: - switch (MASK_AND_SHIFT(data->pin_cfg[2], ADT7462_PIN24)) { - case 0: - return 6250; - case 1: - return 13000; - case 2: - return 9400; - case 3: - return 7800; - } - case 11: - case 12: - if (data->pin_cfg[3] >> ADT7462_PIN28_SHIFT == - ADT7462_PIN28_VOLT && - !(data->pin_cfg[0] & ADT7462_VID_INPUT)) - return 7800; - } - return 0; -} - -static int temp_enabled(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - case 2: - return 1; - case 1: - if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) - return 1; - break; - case 3: - if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) - return 1; - break; - } - return 0; -} - -static const char *temp_label(struct adt7462_data *data, int which) -{ - switch (which) { - case 0: - return "local"; - case 1: - if (data->pin_cfg[0] & ADT7462_DIODE1_INPUT) - return "remote1"; - break; - case 2: - return "remote2"; - case 3: - if (data->pin_cfg[0] & ADT7462_DIODE3_INPUT) - return "remote3"; - break; - } - return "N/A"; -} - -/* Map Trange register values to mC */ -#define NUM_TRANGE_VALUES 16 -static const int trange_values[NUM_TRANGE_VALUES] = { - 2000, - 2500, - 3300, - 4000, - 5000, - 6700, - 8000, - 10000, - 13300, - 16000, - 20000, - 26700, - 32000, - 40000, - 53300, - 80000 -}; - -static int find_trange_value(int trange) -{ - int i; - - for (i = 0; i < NUM_TRANGE_VALUES; i++) - if (trange_values[i] == trange) - return i; - - return -ENODEV; -} - -static struct adt7462_data *adt7462_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - unsigned long local_jiffies = jiffies; - int i; - - mutex_lock(&data->lock); - if (time_before(local_jiffies, data->sensors_last_updated + - SENSOR_REFRESH_INTERVAL) - && data->sensors_valid) - goto no_sensor_update; - - for (i = 0; i < ADT7462_TEMP_COUNT; i++) { - /* - * Reading the fractional register locks the integral - * register until both have been read. - */ - data->temp_frac[i] = i2c_smbus_read_byte_data(client, - ADT7462_TEMP_REG(i)); - data->temp[i] = i2c_smbus_read_byte_data(client, - ADT7462_TEMP_REG(i) + 1); - } - - for (i = 0; i < ADT7462_FAN_COUNT; i++) - data->fan[i] = adt7462_read_word_data(client, - ADT7462_REG_FAN(i)); - - data->fan_enabled = i2c_smbus_read_byte_data(client, - ADT7462_REG_FAN_ENABLE); - - for (i = 0; i < ADT7462_PWM_COUNT; i++) - data->pwm[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_PWM(i)); - - for (i = 0; i < ADT7462_PIN_CFG_REG_COUNT; i++) - data->pin_cfg[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_PIN_CFG(i)); - - for (i = 0; i < ADT7462_VOLT_COUNT; i++) { - int reg = ADT7462_REG_VOLT(data, i); - if (!reg) - data->voltages[i] = 0; - else - data->voltages[i] = i2c_smbus_read_byte_data(client, - reg); - } - - data->alarms[0] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM1); - data->alarms[1] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM2); - data->alarms[2] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM3); - data->alarms[3] = i2c_smbus_read_byte_data(client, ADT7462_REG_ALARM4); - - data->sensors_last_updated = local_jiffies; - data->sensors_valid = 1; - -no_sensor_update: - if (time_before(local_jiffies, data->limits_last_updated + - LIMIT_REFRESH_INTERVAL) - && data->limits_valid) - goto out; - - for (i = 0; i < ADT7462_TEMP_COUNT; i++) { - data->temp_min[i] = i2c_smbus_read_byte_data(client, - ADT7462_TEMP_MIN_REG(i)); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - ADT7462_TEMP_MAX_REG(i)); - } - - for (i = 0; i < ADT7462_FAN_COUNT; i++) - data->fan_min[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_FAN_MIN(i)); - - for (i = 0; i < ADT7462_VOLT_COUNT; i++) { - int reg = ADT7462_REG_VOLT_MAX(data, i); - data->volt_max[i] = - (reg ? i2c_smbus_read_byte_data(client, reg) : 0); - - reg = ADT7462_REG_VOLT_MIN(data, i); - data->volt_min[i] = - (reg ? i2c_smbus_read_byte_data(client, reg) : 0); - } - - for (i = 0; i < ADT7462_PWM_COUNT; i++) { - data->pwm_min[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_PWM_MIN(i)); - data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_PWM_TMIN(i)); - data->pwm_trange[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_PWM_TRANGE(i)); - data->pwm_cfg[i] = i2c_smbus_read_byte_data(client, - ADT7462_REG_PWM_CFG(i)); - } - - data->pwm_max = i2c_smbus_read_byte_data(client, ADT7462_REG_PWM_MAX); - - data->cfg2 = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); - - data->limits_last_updated = local_jiffies; - data->limits_valid = 1; - -out: - mutex_unlock(&data->lock); - return data; -} - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - - if (!temp_enabled(data, attr->index)) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d\n", 1000 * (data->temp_min[attr->index] - 64)); -} - -static ssize_t set_temp_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000) + 64; - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->temp_min[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_TEMP_MIN_REG(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - - if (!temp_enabled(data, attr->index)) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d\n", 1000 * (data->temp_max[attr->index] - 64)); -} - -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000) + 64; - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->temp_max[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_TEMP_MAX_REG(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - u8 frac = data->temp_frac[attr->index] >> TEMP_FRAC_OFFSET; - - if (!temp_enabled(data, attr->index)) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d\n", 1000 * (data->temp[attr->index] - 64) + - 250 * frac); -} - -static ssize_t show_temp_label(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - - return sprintf(buf, "%s\n", temp_label(data, attr->index)); -} - -static ssize_t show_volt_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - int x = voltage_multiplier(data, attr->index); - - x *= data->volt_max[attr->index]; - x /= 1000; /* convert from uV to mV */ - - return sprintf(buf, "%d\n", x); -} - -static ssize_t set_volt_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - int x = voltage_multiplier(data, attr->index); - long temp; - - if (kstrtol(buf, 10, &temp) || !x) - return -EINVAL; - - temp *= 1000; /* convert mV to uV */ - temp = DIV_ROUND_CLOSEST(temp, x); - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->volt_max[attr->index] = temp; - i2c_smbus_write_byte_data(client, - ADT7462_REG_VOLT_MAX(data, attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_volt_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - int x = voltage_multiplier(data, attr->index); - - x *= data->volt_min[attr->index]; - x /= 1000; /* convert from uV to mV */ - - return sprintf(buf, "%d\n", x); -} - -static ssize_t set_volt_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - int x = voltage_multiplier(data, attr->index); - long temp; - - if (kstrtol(buf, 10, &temp) || !x) - return -EINVAL; - - temp *= 1000; /* convert mV to uV */ - temp = DIV_ROUND_CLOSEST(temp, x); - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->volt_min[attr->index] = temp; - i2c_smbus_write_byte_data(client, - ADT7462_REG_VOLT_MIN(data, attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_voltage(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - int x = voltage_multiplier(data, attr->index); - - x *= data->voltages[attr->index]; - x /= 1000; /* convert from uV to mV */ - - return sprintf(buf, "%d\n", x); -} - -static ssize_t show_voltage_label(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - - return sprintf(buf, "%s\n", voltage_label(data, attr->index)); -} - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - int reg = attr->index >> ADT7462_ALARM_REG_SHIFT; - int mask = attr->index & ADT7462_ALARM_FLAG_MASK; - - if (data->alarms[reg] & mask) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static int fan_enabled(struct adt7462_data *data, int fan) -{ - return data->fan_enabled & (1 << fan); -} - -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - u16 temp; - - /* Only the MSB of the min fan period is stored... */ - temp = data->fan_min[attr->index]; - temp <<= 8; - - if (!fan_enabled(data, attr->index) || - !FAN_DATA_VALID(temp)) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d\n", FAN_PERIOD_TO_RPM(temp)); -} - -static ssize_t set_fan_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp) || !temp || - !fan_enabled(data, attr->index)) - return -EINVAL; - - temp = FAN_RPM_TO_PERIOD(temp); - temp >>= 8; - temp = SENSORS_LIMIT(temp, 1, 255); - - mutex_lock(&data->lock); - data->fan_min[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_FAN_MIN(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - - if (!fan_enabled(data, attr->index) || - !FAN_DATA_VALID(data->fan[attr->index])) - return sprintf(buf, "0\n"); - - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan[attr->index])); -} - -static ssize_t show_force_pwm_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct adt7462_data *data = adt7462_update_device(dev); - return sprintf(buf, "%d\n", (data->cfg2 & ADT7462_FSPD_MASK ? 1 : 0)); -} - -static ssize_t set_force_pwm_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - u8 reg; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - mutex_lock(&data->lock); - reg = i2c_smbus_read_byte_data(client, ADT7462_REG_CFG2); - if (temp) - reg |= ADT7462_FSPD_MASK; - else - reg &= ~ADT7462_FSPD_MASK; - data->cfg2 = reg; - i2c_smbus_write_byte_data(client, ADT7462_REG_CFG2, reg); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - return sprintf(buf, "%d\n", data->pwm[attr->index]); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM(attr->index), temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct adt7462_data *data = adt7462_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_max); -} - -static ssize_t set_pwm_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm_max = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MAX, temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_min[attr->index]); -} - -static ssize_t set_pwm_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm_min[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_MIN(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_hyst(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - return sprintf(buf, "%d\n", 1000 * - (data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK)); -} - -static ssize_t set_pwm_hyst(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = SENSORS_LIMIT(temp, 0, 15); - - /* package things up */ - temp &= ADT7462_PWM_HYST_MASK; - temp |= data->pwm_trange[attr->index] & ADT7462_PWM_RANGE_MASK; - - mutex_lock(&data->lock); - data->pwm_trange[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_tmax(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - - /* tmax = tmin + trange */ - int trange = trange_values[data->pwm_trange[attr->index] >> - ADT7462_PWM_RANGE_SHIFT]; - int tmin = (data->pwm_tmin[attr->index] - 64) * 1000; - - return sprintf(buf, "%d\n", tmin + trange); -} - -static ssize_t set_pwm_tmax(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - int temp; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - int tmin, trange_value; - long trange; - - if (kstrtol(buf, 10, &trange)) - return -EINVAL; - - /* trange = tmax - tmin */ - tmin = (data->pwm_tmin[attr->index] - 64) * 1000; - trange_value = find_trange_value(trange - tmin); - - if (trange_value < 0) - return -EINVAL; - - temp = trange_value << ADT7462_PWM_RANGE_SHIFT; - temp |= data->pwm_trange[attr->index] & ADT7462_PWM_HYST_MASK; - - mutex_lock(&data->lock); - data->pwm_trange[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TRANGE(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_tmin(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - return sprintf(buf, "%d\n", 1000 * (data->pwm_tmin[attr->index] - 64)); -} - -static ssize_t set_pwm_tmin(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000) + 64; - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm_tmin[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_TMIN(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_auto(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - int cfg = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; - - switch (cfg) { - case 4: /* off */ - return sprintf(buf, "0\n"); - case 7: /* manual */ - return sprintf(buf, "1\n"); - default: /* automatic */ - return sprintf(buf, "2\n"); - } -} - -static void set_pwm_channel(struct i2c_client *client, - struct adt7462_data *data, - int which, - int value) -{ - int temp = data->pwm_cfg[which] & ~ADT7462_PWM_CHANNEL_MASK; - temp |= value << ADT7462_PWM_CHANNEL_SHIFT; - - mutex_lock(&data->lock); - data->pwm_cfg[which] = temp; - i2c_smbus_write_byte_data(client, ADT7462_REG_PWM_CFG(which), temp); - mutex_unlock(&data->lock); -} - -static ssize_t set_pwm_auto(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - switch (temp) { - case 0: /* off */ - set_pwm_channel(client, data, attr->index, 4); - return count; - case 1: /* manual */ - set_pwm_channel(client, data, attr->index, 7); - return count; - default: - return -EINVAL; - } -} - -static ssize_t show_pwm_auto_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7462_data *data = adt7462_update_device(dev); - int channel = data->pwm_cfg[attr->index] >> ADT7462_PWM_CHANNEL_SHIFT; - - switch (channel) { - case 0: /* temp[1234] only */ - case 1: - case 2: - case 3: - return sprintf(buf, "%d\n", (1 << channel)); - case 5: /* temp1 & temp4 */ - return sprintf(buf, "9\n"); - case 6: - return sprintf(buf, "15\n"); - default: - return sprintf(buf, "0\n"); - } -} - -static int cvt_auto_temp(int input) -{ - if (input == 0xF) - return 6; - if (input == 0x9) - return 5; - if (input < 1 || !is_power_of_2(input)) - return -EINVAL; - return ilog2(input); -} - -static ssize_t set_pwm_auto_temp(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = cvt_auto_temp(temp); - if (temp < 0) - return temp; - - set_pwm_channel(client, data, attr->index, temp); - - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 2); -static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 3); - -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 2); -static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 3); - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); - -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3); - -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM1 | ADT7462_LT_ALARM); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM1 | ADT7462_R1T_ALARM); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM1 | ADT7462_R2T_ALARM); -static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM1 | ADT7462_R3T_ALARM); - -static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 0); -static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 1); -static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 2); -static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 3); -static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 4); -static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 5); -static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 6); -static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 7); -static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 8); -static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 9); -static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 10); -static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 11); -static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, show_volt_max, - set_volt_max, 12); - -static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 0); -static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 1); -static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 2); -static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 3); -static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 4); -static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 5); -static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 6); -static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 7); -static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 8); -static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 9); -static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 10); -static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 11); -static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, show_volt_min, - set_volt_min, 12); - -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_voltage, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_voltage, NULL, 3); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 4); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 5); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 6); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_voltage, NULL, 7); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_voltage, NULL, 8); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_voltage, NULL, 9); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_voltage, NULL, 10); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_voltage, NULL, 11); -static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_voltage, NULL, 12); - -static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_voltage_label, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_voltage_label, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_voltage_label, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, show_voltage_label, NULL, 3); -static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, show_voltage_label, NULL, 4); -static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, show_voltage_label, NULL, 5); -static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_voltage_label, NULL, 6); -static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_voltage_label, NULL, 7); -static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, show_voltage_label, NULL, 8); -static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, show_voltage_label, NULL, 9); -static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, show_voltage_label, NULL, 10); -static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, show_voltage_label, NULL, 11); -static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, show_voltage_label, NULL, 12); - -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V0_ALARM); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V7_ALARM); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V2_ALARM); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V6_ALARM); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V5_ALARM); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V4_ALARM); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V3_ALARM); -static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM2 | ADT7462_V1_ALARM); -static SENSOR_DEVICE_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM3 | ADT7462_V10_ALARM); -static SENSOR_DEVICE_ATTR(in10_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM3 | ADT7462_V9_ALARM); -static SENSOR_DEVICE_ATTR(in11_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM3 | ADT7462_V8_ALARM); -static SENSOR_DEVICE_ATTR(in12_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM3 | ADT7462_V11_ALARM); -static SENSOR_DEVICE_ATTR(in13_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM3 | ADT7462_V12_ALARM); - -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 3); -static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 4); -static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 5); -static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 6); -static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 7); - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F0_ALARM); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F1_ALARM); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F2_ALARM); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F3_ALARM); -static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F4_ALARM); -static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F5_ALARM); -static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F6_ALARM); -static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_alarm, NULL, - ADT7462_ALARM4 | ADT7462_F7_ALARM); - -static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, - show_force_pwm_max, set_force_pwm_max, 0); - -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 3); - -static SENSOR_DEVICE_ATTR(temp1_auto_point1_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_point1_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_point1_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 2); -static SENSOR_DEVICE_ATTR(temp4_auto_point1_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 3); - -static SENSOR_DEVICE_ATTR(temp1_auto_point2_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_point2_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_point2_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 2); -static SENSOR_DEVICE_ATTR(temp4_auto_point2_hyst, S_IWUSR | S_IRUGO, - show_pwm_hyst, set_pwm_hyst, 3); - -static SENSOR_DEVICE_ATTR(temp1_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 2); -static SENSOR_DEVICE_ATTR(temp4_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 3); - -static SENSOR_DEVICE_ATTR(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, - show_pwm_tmax, set_pwm_tmax, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, - show_pwm_tmax, set_pwm_tmax, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_point2_temp, S_IWUSR | S_IRUGO, - show_pwm_tmax, set_pwm_tmax, 2); -static SENSOR_DEVICE_ATTR(temp4_auto_point2_temp, S_IWUSR | S_IRUGO, - show_pwm_tmax, set_pwm_tmax, 3); - -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 1); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 2); -static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 3); - -static struct attribute *adt7462_attr[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - &sensor_dev_attr_temp3_label.dev_attr.attr, - &sensor_dev_attr_temp4_label.dev_attr.attr, - - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_alarm.dev_attr.attr, - - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in10_max.dev_attr.attr, - &sensor_dev_attr_in11_max.dev_attr.attr, - &sensor_dev_attr_in12_max.dev_attr.attr, - &sensor_dev_attr_in13_max.dev_attr.attr, - - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in10_min.dev_attr.attr, - &sensor_dev_attr_in11_min.dev_attr.attr, - &sensor_dev_attr_in12_min.dev_attr.attr, - &sensor_dev_attr_in13_min.dev_attr.attr, - - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_in13_input.dev_attr.attr, - - &sensor_dev_attr_in1_label.dev_attr.attr, - &sensor_dev_attr_in2_label.dev_attr.attr, - &sensor_dev_attr_in3_label.dev_attr.attr, - &sensor_dev_attr_in4_label.dev_attr.attr, - &sensor_dev_attr_in5_label.dev_attr.attr, - &sensor_dev_attr_in6_label.dev_attr.attr, - &sensor_dev_attr_in7_label.dev_attr.attr, - &sensor_dev_attr_in8_label.dev_attr.attr, - &sensor_dev_attr_in9_label.dev_attr.attr, - &sensor_dev_attr_in10_label.dev_attr.attr, - &sensor_dev_attr_in11_label.dev_attr.attr, - &sensor_dev_attr_in12_label.dev_attr.attr, - &sensor_dev_attr_in13_label.dev_attr.attr, - - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - &sensor_dev_attr_in8_alarm.dev_attr.attr, - &sensor_dev_attr_in9_alarm.dev_attr.attr, - &sensor_dev_attr_in10_alarm.dev_attr.attr, - &sensor_dev_attr_in11_alarm.dev_attr.attr, - &sensor_dev_attr_in12_alarm.dev_attr.attr, - &sensor_dev_attr_in13_alarm.dev_attr.attr, - - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan5_min.dev_attr.attr, - &sensor_dev_attr_fan6_min.dev_attr.attr, - &sensor_dev_attr_fan7_min.dev_attr.attr, - &sensor_dev_attr_fan8_min.dev_attr.attr, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan5_input.dev_attr.attr, - &sensor_dev_attr_fan6_input.dev_attr.attr, - &sensor_dev_attr_fan7_input.dev_attr.attr, - &sensor_dev_attr_fan8_input.dev_attr.attr, - - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - &sensor_dev_attr_fan5_alarm.dev_attr.attr, - &sensor_dev_attr_fan6_alarm.dev_attr.attr, - &sensor_dev_attr_fan7_alarm.dev_attr.attr, - &sensor_dev_attr_fan8_alarm.dev_attr.attr, - - &sensor_dev_attr_force_pwm_max.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm4.dev_attr.attr, - - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, - - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, - - &sensor_dev_attr_temp1_auto_point1_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point1_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_auto_point1_hyst.dev_attr.attr, - - &sensor_dev_attr_temp1_auto_point2_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point2_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point2_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_auto_point2_hyst.dev_attr.attr, - - &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp4_auto_point1_temp.dev_attr.attr, - - &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp4_auto_point2_temp.dev_attr.attr, - - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm4_enable.dev_attr.attr, - - &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, - NULL -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adt7462_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int vendor, device, revision; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - vendor = i2c_smbus_read_byte_data(client, ADT7462_REG_VENDOR); - if (vendor != ADT7462_VENDOR) - return -ENODEV; - - device = i2c_smbus_read_byte_data(client, ADT7462_REG_DEVICE); - if (device != ADT7462_DEVICE) - return -ENODEV; - - revision = i2c_smbus_read_byte_data(client, ADT7462_REG_REVISION); - if (revision != ADT7462_REVISION) - return -ENODEV; - - strlcpy(info->type, "adt7462", I2C_NAME_SIZE); - - return 0; -} - -static int adt7462_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt7462_data *data; - int err; - - data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); - - dev_info(&client->dev, "%s chip found\n", client->name); - - /* Register sysfs hooks */ - data->attrs.attrs = adt7462_attr; - err = sysfs_create_group(&client->dev.kobj, &data->attrs); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &data->attrs); -exit_free: - kfree(data); -exit: - return err; -} - -static int adt7462_remove(struct i2c_client *client) -{ - struct adt7462_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->attrs); - kfree(data); - return 0; -} - -module_i2c_driver(adt7462_driver); - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("ADT7462 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adt7470.c b/ANDROID_3.4.5/drivers/hwmon/adt7470.c deleted file mode 100644 index 54ec8905..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adt7470.c +++ /dev/null @@ -1,1324 +0,0 @@ -/* - * A hwmon driver for the Analog Devices ADT7470 - * Copyright (C) 2007 IBM - * - * Author: Darrick J. Wong - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; - -/* ADT7470 registers */ -#define ADT7470_REG_BASE_ADDR 0x20 -#define ADT7470_REG_TEMP_BASE_ADDR 0x20 -#define ADT7470_REG_TEMP_MAX_ADDR 0x29 -#define ADT7470_REG_FAN_BASE_ADDR 0x2A -#define ADT7470_REG_FAN_MAX_ADDR 0x31 -#define ADT7470_REG_PWM_BASE_ADDR 0x32 -#define ADT7470_REG_PWM_MAX_ADDR 0x35 -#define ADT7470_REG_PWM_MAX_BASE_ADDR 0x38 -#define ADT7470_REG_PWM_MAX_MAX_ADDR 0x3B -#define ADT7470_REG_CFG 0x40 -#define ADT7470_FSPD_MASK 0x04 -#define ADT7470_REG_ALARM1 0x41 -#define ADT7470_R1T_ALARM 0x01 -#define ADT7470_R2T_ALARM 0x02 -#define ADT7470_R3T_ALARM 0x04 -#define ADT7470_R4T_ALARM 0x08 -#define ADT7470_R5T_ALARM 0x10 -#define ADT7470_R6T_ALARM 0x20 -#define ADT7470_R7T_ALARM 0x40 -#define ADT7470_OOL_ALARM 0x80 -#define ADT7470_REG_ALARM2 0x42 -#define ADT7470_R8T_ALARM 0x01 -#define ADT7470_R9T_ALARM 0x02 -#define ADT7470_R10T_ALARM 0x04 -#define ADT7470_FAN1_ALARM 0x10 -#define ADT7470_FAN2_ALARM 0x20 -#define ADT7470_FAN3_ALARM 0x40 -#define ADT7470_FAN4_ALARM 0x80 -#define ADT7470_REG_TEMP_LIMITS_BASE_ADDR 0x44 -#define ADT7470_REG_TEMP_LIMITS_MAX_ADDR 0x57 -#define ADT7470_REG_FAN_MIN_BASE_ADDR 0x58 -#define ADT7470_REG_FAN_MIN_MAX_ADDR 0x5F -#define ADT7470_REG_FAN_MAX_BASE_ADDR 0x60 -#define ADT7470_REG_FAN_MAX_MAX_ADDR 0x67 -#define ADT7470_REG_PWM_CFG_BASE_ADDR 0x68 -#define ADT7470_REG_PWM12_CFG 0x68 -#define ADT7470_PWM2_AUTO_MASK 0x40 -#define ADT7470_PWM1_AUTO_MASK 0x80 -#define ADT7470_PWM_AUTO_MASK 0xC0 -#define ADT7470_REG_PWM34_CFG 0x69 -#define ADT7470_PWM3_AUTO_MASK 0x40 -#define ADT7470_PWM4_AUTO_MASK 0x80 -#define ADT7470_REG_PWM_MIN_BASE_ADDR 0x6A -#define ADT7470_REG_PWM_MIN_MAX_ADDR 0x6D -#define ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR 0x6E -#define ADT7470_REG_PWM_TEMP_MIN_MAX_ADDR 0x71 -#define ADT7470_REG_ACOUSTICS12 0x75 -#define ADT7470_REG_ACOUSTICS34 0x76 -#define ADT7470_REG_DEVICE 0x3D -#define ADT7470_REG_VENDOR 0x3E -#define ADT7470_REG_REVISION 0x3F -#define ADT7470_REG_ALARM1_MASK 0x72 -#define ADT7470_REG_ALARM2_MASK 0x73 -#define ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR 0x7C -#define ADT7470_REG_PWM_AUTO_TEMP_MAX_ADDR 0x7D -#define ADT7470_REG_MAX_ADDR 0x81 - -#define ADT7470_TEMP_COUNT 10 -#define ADT7470_TEMP_REG(x) (ADT7470_REG_TEMP_BASE_ADDR + (x)) -#define ADT7470_TEMP_MIN_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + ((x) * 2)) -#define ADT7470_TEMP_MAX_REG(x) (ADT7470_REG_TEMP_LIMITS_BASE_ADDR + \ - ((x) * 2) + 1) - -#define ADT7470_FAN_COUNT 4 -#define ADT7470_REG_FAN(x) (ADT7470_REG_FAN_BASE_ADDR + ((x) * 2)) -#define ADT7470_REG_FAN_MIN(x) (ADT7470_REG_FAN_MIN_BASE_ADDR + ((x) * 2)) -#define ADT7470_REG_FAN_MAX(x) (ADT7470_REG_FAN_MAX_BASE_ADDR + ((x) * 2)) - -#define ADT7470_PWM_COUNT 4 -#define ADT7470_REG_PWM(x) (ADT7470_REG_PWM_BASE_ADDR + (x)) -#define ADT7470_REG_PWM_MAX(x) (ADT7470_REG_PWM_MAX_BASE_ADDR + (x)) -#define ADT7470_REG_PWM_MIN(x) (ADT7470_REG_PWM_MIN_BASE_ADDR + (x)) -#define ADT7470_REG_PWM_TMIN(x) (ADT7470_REG_PWM_TEMP_MIN_BASE_ADDR + (x)) -#define ADT7470_REG_PWM_CFG(x) (ADT7470_REG_PWM_CFG_BASE_ADDR + ((x) / 2)) -#define ADT7470_REG_PWM_AUTO_TEMP(x) (ADT7470_REG_PWM_AUTO_TEMP_BASE_ADDR + \ - ((x) / 2)) - -#define ALARM2(x) ((x) << 8) - -#define ADT7470_VENDOR 0x41 -#define ADT7470_DEVICE 0x70 -/* datasheet only mentions a revision 2 */ -#define ADT7470_REVISION 0x02 - -/* "all temps" according to hwmon sysfs interface spec */ -#define ADT7470_PWM_ALL_TEMPS 0x3FF - -/* How often do we reread sensors values? (In jiffies) */ -#define SENSOR_REFRESH_INTERVAL (5 * HZ) - -/* How often do we reread sensor limit values? (In jiffies) */ -#define LIMIT_REFRESH_INTERVAL (60 * HZ) - -/* Wait at least 200ms per sensor for 10 sensors */ -#define TEMP_COLLECTION_TIME 2000 - -/* auto update thing won't fire more than every 2s */ -#define AUTO_UPDATE_INTERVAL 2000 - -/* datasheet says to divide this number by the fan reading to get fan rpm */ -#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) -#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM -#define FAN_PERIOD_INVALID 65535 -#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) - -struct adt7470_data { - struct device *hwmon_dev; - struct attribute_group attrs; - struct mutex lock; - char sensors_valid; - char limits_valid; - unsigned long sensors_last_updated; /* In jiffies */ - unsigned long limits_last_updated; /* In jiffies */ - - int num_temp_sensors; /* -1 = probe */ - int temperatures_probed; - - s8 temp[ADT7470_TEMP_COUNT]; - s8 temp_min[ADT7470_TEMP_COUNT]; - s8 temp_max[ADT7470_TEMP_COUNT]; - u16 fan[ADT7470_FAN_COUNT]; - u16 fan_min[ADT7470_FAN_COUNT]; - u16 fan_max[ADT7470_FAN_COUNT]; - u16 alarm; - u16 alarms_mask; - u8 force_pwm_max; - u8 pwm[ADT7470_PWM_COUNT]; - u8 pwm_max[ADT7470_PWM_COUNT]; - u8 pwm_automatic[ADT7470_PWM_COUNT]; - u8 pwm_min[ADT7470_PWM_COUNT]; - s8 pwm_tmin[ADT7470_PWM_COUNT]; - u8 pwm_auto_temp[ADT7470_PWM_COUNT]; - - struct task_struct *auto_update; - struct completion auto_update_stop; - unsigned int auto_update_interval; -}; - -static int adt7470_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adt7470_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adt7470_remove(struct i2c_client *client); - -static const struct i2c_device_id adt7470_id[] = { - { "adt7470", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7470_id); - -static struct i2c_driver adt7470_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adt7470", - }, - .probe = adt7470_probe, - .remove = adt7470_remove, - .id_table = adt7470_id, - .detect = adt7470_detect, - .address_list = normal_i2c, -}; - -/* - * 16-bit registers on the ADT7470 are low-byte first. The data sheet says - * that the low byte must be read before the high byte. - */ -static inline int adt7470_read_word_data(struct i2c_client *client, u8 reg) -{ - u16 foo; - foo = i2c_smbus_read_byte_data(client, reg); - foo |= ((u16)i2c_smbus_read_byte_data(client, reg + 1) << 8); - return foo; -} - -static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg, - u16 value) -{ - return i2c_smbus_write_byte_data(client, reg, value & 0xFF) - && i2c_smbus_write_byte_data(client, reg + 1, value >> 8); -} - -static void adt7470_init_client(struct i2c_client *client) -{ - int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - - if (reg < 0) { - dev_err(&client->dev, "cannot read configuration register\n"); - } else { - /* start monitoring (and do a self-test) */ - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3); - } -} - -/* Probe for temperature sensors. Assumes lock is held */ -static int adt7470_read_temperatures(struct i2c_client *client, - struct adt7470_data *data) -{ - unsigned long res; - int i; - u8 cfg, pwm[4], pwm_cfg[2]; - - /* save pwm[1-4] config register */ - pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0)); - pwm_cfg[1] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(2)); - - /* set manual pwm to whatever it is set to now */ - for (i = 0; i < ADT7470_FAN_COUNT; i++) - pwm[i] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM(i)); - - /* put pwm in manual mode */ - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), - pwm_cfg[0] & ~(ADT7470_PWM_AUTO_MASK)); - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), - pwm_cfg[1] & ~(ADT7470_PWM_AUTO_MASK)); - - /* write pwm control to whatever it was */ - for (i = 0; i < ADT7470_FAN_COUNT; i++) - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(i), pwm[i]); - - /* start reading temperature sensors */ - cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - cfg |= 0x80; - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); - - /* Delay is 200ms * number of temp sensors. */ - res = msleep_interruptible((data->num_temp_sensors >= 0 ? - data->num_temp_sensors * 200 : - TEMP_COLLECTION_TIME)); - - /* done reading temperature sensors */ - cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - cfg &= ~0x80; - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); - - /* restore pwm[1-4] config registers */ - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]); - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]); - - if (res) { - pr_err("ha ha, interrupted\n"); - return -EAGAIN; - } - - /* Only count fans if we have to */ - if (data->num_temp_sensors >= 0) - return 0; - - for (i = 0; i < ADT7470_TEMP_COUNT; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_REG(i)); - if (data->temp[i]) - data->num_temp_sensors = i + 1; - } - data->temperatures_probed = 1; - return 0; -} - -static int adt7470_update_thread(void *p) -{ - struct i2c_client *client = p; - struct adt7470_data *data = i2c_get_clientdata(client); - - while (!kthread_should_stop()) { - mutex_lock(&data->lock); - adt7470_read_temperatures(client, data); - mutex_unlock(&data->lock); - if (kthread_should_stop()) - break; - msleep_interruptible(data->auto_update_interval); - } - - complete_all(&data->auto_update_stop); - return 0; -} - -static struct adt7470_data *adt7470_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - unsigned long local_jiffies = jiffies; - u8 cfg; - int i; - int need_sensors = 1; - int need_limits = 1; - - /* - * Figure out if we need to update the shadow registers. - * Lockless means that we may occasionally report out of - * date data. - */ - if (time_before(local_jiffies, data->sensors_last_updated + - SENSOR_REFRESH_INTERVAL) && - data->sensors_valid) - need_sensors = 0; - - if (time_before(local_jiffies, data->limits_last_updated + - LIMIT_REFRESH_INTERVAL) && - data->limits_valid) - need_limits = 0; - - if (!need_sensors && !need_limits) - return data; - - mutex_lock(&data->lock); - if (!need_sensors) - goto no_sensor_update; - - if (!data->temperatures_probed) - adt7470_read_temperatures(client, data); - else - for (i = 0; i < ADT7470_TEMP_COUNT; i++) - data->temp[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_REG(i)); - - for (i = 0; i < ADT7470_FAN_COUNT; i++) - data->fan[i] = adt7470_read_word_data(client, - ADT7470_REG_FAN(i)); - - for (i = 0; i < ADT7470_PWM_COUNT; i++) { - int reg; - int reg_mask; - - data->pwm[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM(i)); - - if (i % 2) - reg_mask = ADT7470_PWM2_AUTO_MASK; - else - reg_mask = ADT7470_PWM1_AUTO_MASK; - - reg = ADT7470_REG_PWM_CFG(i); - if (i2c_smbus_read_byte_data(client, reg) & reg_mask) - data->pwm_automatic[i] = 1; - else - data->pwm_automatic[i] = 0; - - reg = ADT7470_REG_PWM_AUTO_TEMP(i); - cfg = i2c_smbus_read_byte_data(client, reg); - if (!(i % 2)) - data->pwm_auto_temp[i] = cfg >> 4; - else - data->pwm_auto_temp[i] = cfg & 0xF; - } - - if (i2c_smbus_read_byte_data(client, ADT7470_REG_CFG) & - ADT7470_FSPD_MASK) - data->force_pwm_max = 1; - else - data->force_pwm_max = 0; - - data->alarm = i2c_smbus_read_byte_data(client, ADT7470_REG_ALARM1); - if (data->alarm & ADT7470_OOL_ALARM) - data->alarm |= ALARM2(i2c_smbus_read_byte_data(client, - ADT7470_REG_ALARM2)); - data->alarms_mask = adt7470_read_word_data(client, - ADT7470_REG_ALARM1_MASK); - - data->sensors_last_updated = local_jiffies; - data->sensors_valid = 1; - -no_sensor_update: - if (!need_limits) - goto out; - - for (i = 0; i < ADT7470_TEMP_COUNT; i++) { - data->temp_min[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_MIN_REG(i)); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - ADT7470_TEMP_MAX_REG(i)); - } - - for (i = 0; i < ADT7470_FAN_COUNT; i++) { - data->fan_min[i] = adt7470_read_word_data(client, - ADT7470_REG_FAN_MIN(i)); - data->fan_max[i] = adt7470_read_word_data(client, - ADT7470_REG_FAN_MAX(i)); - } - - for (i = 0; i < ADT7470_PWM_COUNT; i++) { - data->pwm_max[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM_MAX(i)); - data->pwm_min[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM_MIN(i)); - data->pwm_tmin[i] = i2c_smbus_read_byte_data(client, - ADT7470_REG_PWM_TMIN(i)); - } - - data->limits_last_updated = local_jiffies; - data->limits_valid = 1; - -out: - mutex_unlock(&data->lock); - return data; -} - -static ssize_t show_auto_update_interval(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", data->auto_update_interval); -} - -static ssize_t set_auto_update_interval(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 60000); - - mutex_lock(&data->lock); - data->auto_update_interval = temp; - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_num_temp_sensors(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", data->num_temp_sensors); -} - -static ssize_t set_num_temp_sensors(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, -1, 10); - - mutex_lock(&data->lock); - data->num_temp_sensors = temp; - if (temp < 0) - data->temperatures_probed = 0; - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", 1000 * data->temp_min[attr->index]); -} - -static ssize_t set_temp_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->temp_min[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7470_TEMP_MIN_REG(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", 1000 * data->temp_max[attr->index]); -} - -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->temp_max[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7470_TEMP_MAX_REG(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", 1000 * data->temp[attr->index]); -} - -static ssize_t show_alarm_mask(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct adt7470_data *data = adt7470_update_device(dev); - - return sprintf(buf, "%x\n", data->alarms_mask); -} - -static ssize_t show_fan_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - - if (FAN_DATA_VALID(data->fan_max[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan_max[attr->index])); - else - return sprintf(buf, "0\n"); -} - -static ssize_t set_fan_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp) || !temp) - return -EINVAL; - - temp = FAN_RPM_TO_PERIOD(temp); - temp = SENSORS_LIMIT(temp, 1, 65534); - - mutex_lock(&data->lock); - data->fan_max[attr->index] = temp; - adt7470_write_word_data(client, ADT7470_REG_FAN_MAX(attr->index), temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - - if (FAN_DATA_VALID(data->fan_min[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan_min[attr->index])); - else - return sprintf(buf, "0\n"); -} - -static ssize_t set_fan_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp) || !temp) - return -EINVAL; - - temp = FAN_RPM_TO_PERIOD(temp); - temp = SENSORS_LIMIT(temp, 1, 65534); - - mutex_lock(&data->lock); - data->fan_min[attr->index] = temp; - adt7470_write_word_data(client, ADT7470_REG_FAN_MIN(attr->index), temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - - if (FAN_DATA_VALID(data->fan[attr->index])) - return sprintf(buf, "%d\n", - FAN_PERIOD_TO_RPM(data->fan[attr->index])); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_force_pwm_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", data->force_pwm_max); -} - -static ssize_t set_force_pwm_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - u8 reg; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - mutex_lock(&data->lock); - data->force_pwm_max = temp; - reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - if (temp) - reg |= ADT7470_FSPD_MASK; - else - reg &= ~ADT7470_FSPD_MASK; - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", data->pwm[attr->index]); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM(attr->index), temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_max[attr->index]); -} - -static ssize_t set_pwm_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm_max[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_MAX(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_min[attr->index]); -} - -static ssize_t set_pwm_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm_min[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_MIN(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_tmax(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - /* the datasheet says that tmax = tmin + 20C */ - return sprintf(buf, "%d\n", 1000 * (20 + data->pwm_tmin[attr->index])); -} - -static ssize_t show_pwm_tmin(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", 1000 * data->pwm_tmin[attr->index]); -} - -static ssize_t set_pwm_tmin(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - long temp; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = DIV_ROUND_CLOSEST(temp, 1000); - temp = SENSORS_LIMIT(temp, 0, 255); - - mutex_lock(&data->lock); - data->pwm_tmin[attr->index] = temp; - i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_TMIN(attr->index), - temp); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_auto(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - return sprintf(buf, "%d\n", 1 + data->pwm_automatic[attr->index]); -} - -static ssize_t set_pwm_auto(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); - int pwm_auto_reg_mask; - long temp; - u8 reg; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - if (attr->index % 2) - pwm_auto_reg_mask = ADT7470_PWM2_AUTO_MASK; - else - pwm_auto_reg_mask = ADT7470_PWM1_AUTO_MASK; - - if (temp != 2 && temp != 1) - return -EINVAL; - temp--; - - mutex_lock(&data->lock); - data->pwm_automatic[attr->index] = temp; - reg = i2c_smbus_read_byte_data(client, pwm_auto_reg); - if (temp) - reg |= pwm_auto_reg_mask; - else - reg &= ~pwm_auto_reg_mask; - i2c_smbus_write_byte_data(client, pwm_auto_reg, reg); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm_auto_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - u8 ctrl = data->pwm_auto_temp[attr->index]; - - if (ctrl) - return sprintf(buf, "%d\n", 1 << (ctrl - 1)); - else - return sprintf(buf, "%d\n", ADT7470_PWM_ALL_TEMPS); -} - -static int cvt_auto_temp(int input) -{ - if (input == ADT7470_PWM_ALL_TEMPS) - return 0; - if (input < 1 || !is_power_of_2(input)) - return -EINVAL; - return ilog2(input) + 1; -} - -static ssize_t set_pwm_auto_temp(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); - int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); - long temp; - u8 reg; - - if (kstrtol(buf, 10, &temp)) - return -EINVAL; - - temp = cvt_auto_temp(temp); - if (temp < 0) - return temp; - - mutex_lock(&data->lock); - data->pwm_automatic[attr->index] = temp; - reg = i2c_smbus_read_byte_data(client, pwm_auto_reg); - - if (!(attr->index % 2)) { - reg &= 0xF; - reg |= (temp << 4) & 0xF0; - } else { - reg &= 0xF0; - reg |= temp & 0xF; - } - - i2c_smbus_write_byte_data(client, pwm_auto_reg, reg); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct adt7470_data *data = adt7470_update_device(dev); - - if (data->alarm & attr->index) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL); -static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, - set_num_temp_sensors); -static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO, - show_auto_update_interval, set_auto_update_interval); - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 2); -static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 3); -static SENSOR_DEVICE_ATTR(temp5_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 4); -static SENSOR_DEVICE_ATTR(temp6_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 5); -static SENSOR_DEVICE_ATTR(temp7_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 6); -static SENSOR_DEVICE_ATTR(temp8_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 7); -static SENSOR_DEVICE_ATTR(temp9_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 8); -static SENSOR_DEVICE_ATTR(temp10_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 9); - -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 2); -static SENSOR_DEVICE_ATTR(temp4_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 3); -static SENSOR_DEVICE_ATTR(temp5_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 4); -static SENSOR_DEVICE_ATTR(temp6_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 5); -static SENSOR_DEVICE_ATTR(temp7_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 6); -static SENSOR_DEVICE_ATTR(temp8_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 7); -static SENSOR_DEVICE_ATTR(temp9_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 8); -static SENSOR_DEVICE_ATTR(temp10_min, S_IWUSR | S_IRUGO, show_temp_min, - set_temp_min, 9); - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(temp10_input, S_IRUGO, show_temp, NULL, 9); - -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R1T_ALARM); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R2T_ALARM); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R3T_ALARM); -static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R4T_ALARM); -static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R5T_ALARM); -static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R6T_ALARM); -static SENSOR_DEVICE_ATTR(temp7_alarm, S_IRUGO, show_alarm, NULL, - ADT7470_R7T_ALARM); -static SENSOR_DEVICE_ATTR(temp8_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_R8T_ALARM)); -static SENSOR_DEVICE_ATTR(temp9_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_R9T_ALARM)); -static SENSOR_DEVICE_ATTR(temp10_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_R10T_ALARM)); - -static SENSOR_DEVICE_ATTR(fan1_max, S_IWUSR | S_IRUGO, show_fan_max, - set_fan_max, 0); -static SENSOR_DEVICE_ATTR(fan2_max, S_IWUSR | S_IRUGO, show_fan_max, - set_fan_max, 1); -static SENSOR_DEVICE_ATTR(fan3_max, S_IWUSR | S_IRUGO, show_fan_max, - set_fan_max, 2); -static SENSOR_DEVICE_ATTR(fan4_max, S_IWUSR | S_IRUGO, show_fan_max, - set_fan_max, 3); - -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, show_fan_min, - set_fan_min, 3); - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); - -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_FAN1_ALARM)); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_FAN2_ALARM)); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_FAN3_ALARM)); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, - ALARM2(ADT7470_FAN4_ALARM)); - -static SENSOR_DEVICE_ATTR(force_pwm_max, S_IWUSR | S_IRUGO, - show_force_pwm_max, set_force_pwm_max, 0); - -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm_min, set_pwm_min, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm_max, set_pwm_max, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_point1_temp, S_IWUSR | S_IRUGO, - show_pwm_tmin, set_pwm_tmin, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IRUGO, show_pwm_tmax, - NULL, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_point2_temp, S_IRUGO, show_pwm_tmax, - NULL, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_point2_temp, S_IRUGO, show_pwm_tmax, - NULL, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_point2_temp, S_IRUGO, show_pwm_tmax, - NULL, 3); - -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 1); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 2); -static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_auto, - set_pwm_auto, 3); - -static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 1); -static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 2); -static SENSOR_DEVICE_ATTR(pwm4_auto_channels_temp, S_IWUSR | S_IRUGO, - show_pwm_auto_temp, set_pwm_auto_temp, 3); - -static struct attribute *adt7470_attr[] = { - &dev_attr_alarm_mask.attr, - &dev_attr_num_temp_sensors.attr, - &dev_attr_auto_update_interval.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp5_max.dev_attr.attr, - &sensor_dev_attr_temp6_max.dev_attr.attr, - &sensor_dev_attr_temp7_max.dev_attr.attr, - &sensor_dev_attr_temp8_max.dev_attr.attr, - &sensor_dev_attr_temp9_max.dev_attr.attr, - &sensor_dev_attr_temp10_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp5_min.dev_attr.attr, - &sensor_dev_attr_temp6_min.dev_attr.attr, - &sensor_dev_attr_temp7_min.dev_attr.attr, - &sensor_dev_attr_temp8_min.dev_attr.attr, - &sensor_dev_attr_temp9_min.dev_attr.attr, - &sensor_dev_attr_temp10_min.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp7_input.dev_attr.attr, - &sensor_dev_attr_temp8_input.dev_attr.attr, - &sensor_dev_attr_temp9_input.dev_attr.attr, - &sensor_dev_attr_temp10_input.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_alarm.dev_attr.attr, - &sensor_dev_attr_temp5_alarm.dev_attr.attr, - &sensor_dev_attr_temp6_alarm.dev_attr.attr, - &sensor_dev_attr_temp7_alarm.dev_attr.attr, - &sensor_dev_attr_temp8_alarm.dev_attr.attr, - &sensor_dev_attr_temp9_alarm.dev_attr.attr, - &sensor_dev_attr_temp10_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_max.dev_attr.attr, - &sensor_dev_attr_fan2_max.dev_attr.attr, - &sensor_dev_attr_fan3_max.dev_attr.attr, - &sensor_dev_attr_fan4_max.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - &sensor_dev_attr_force_pwm_max.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm4.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm4_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm4_auto_channels_temp.dev_attr.attr, - NULL -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int adt7470_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int vendor, device, revision; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - vendor = i2c_smbus_read_byte_data(client, ADT7470_REG_VENDOR); - if (vendor != ADT7470_VENDOR) - return -ENODEV; - - device = i2c_smbus_read_byte_data(client, ADT7470_REG_DEVICE); - if (device != ADT7470_DEVICE) - return -ENODEV; - - revision = i2c_smbus_read_byte_data(client, ADT7470_REG_REVISION); - if (revision != ADT7470_REVISION) - return -ENODEV; - - strlcpy(info->type, "adt7470", I2C_NAME_SIZE); - - return 0; -} - -static int adt7470_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adt7470_data *data; - int err; - - data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - data->num_temp_sensors = -1; - data->auto_update_interval = AUTO_UPDATE_INTERVAL; - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); - - dev_info(&client->dev, "%s chip found\n", client->name); - - /* Initialize the ADT7470 chip */ - adt7470_init_client(client); - - /* Register sysfs hooks */ - data->attrs.attrs = adt7470_attr; - err = sysfs_create_group(&client->dev.kobj, &data->attrs); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - init_completion(&data->auto_update_stop); - data->auto_update = kthread_run(adt7470_update_thread, client, - dev_name(data->hwmon_dev)); - if (IS_ERR(data->auto_update)) { - err = PTR_ERR(data->auto_update); - goto exit_unregister; - } - - return 0; - -exit_unregister: - hwmon_device_unregister(data->hwmon_dev); -exit_remove: - sysfs_remove_group(&client->dev.kobj, &data->attrs); -exit_free: - kfree(data); -exit: - return err; -} - -static int adt7470_remove(struct i2c_client *client) -{ - struct adt7470_data *data = i2c_get_clientdata(client); - - kthread_stop(data->auto_update); - wait_for_completion(&data->auto_update_stop); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->attrs); - kfree(data); - return 0; -} - -module_i2c_driver(adt7470_driver); - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("ADT7470 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/adt7475.c b/ANDROID_3.4.5/drivers/hwmon/adt7475.c deleted file mode 100644 index df29d13a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/adt7475.c +++ /dev/null @@ -1,1633 +0,0 @@ -/* - * adt7475 - Thermal sensor driver for the ADT7475 chip and derivatives - * Copyright (C) 2007-2008, Advanced Micro Devices, Inc. - * Copyright (C) 2008 Jordan Crouse - * Copyright (C) 2008 Hans de Goede - * Copyright (C) 2009 Jean Delvare - * - * Derived from the lm83 driver by Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Indexes for the sysfs hooks */ - -#define INPUT 0 -#define MIN 1 -#define MAX 2 -#define CONTROL 3 -#define OFFSET 3 -#define AUTOMIN 4 -#define THERM 5 -#define HYSTERSIS 6 - -/* - * These are unique identifiers for the sysfs functions - unlike the - * numbers above, these are not also indexes into an array - */ - -#define ALARM 9 -#define FAULT 10 - -/* 7475 Common Registers */ - -#define REG_DEVREV2 0x12 /* ADT7490 only */ - -#define REG_VTT 0x1E /* ADT7490 only */ -#define REG_EXTEND3 0x1F /* ADT7490 only */ - -#define REG_VOLTAGE_BASE 0x20 -#define REG_TEMP_BASE 0x25 -#define REG_TACH_BASE 0x28 -#define REG_PWM_BASE 0x30 -#define REG_PWM_MAX_BASE 0x38 - -#define REG_DEVID 0x3D -#define REG_VENDID 0x3E -#define REG_DEVID2 0x3F - -#define REG_STATUS1 0x41 -#define REG_STATUS2 0x42 - -#define REG_VID 0x43 /* ADT7476 only */ - -#define REG_VOLTAGE_MIN_BASE 0x44 -#define REG_VOLTAGE_MAX_BASE 0x45 - -#define REG_TEMP_MIN_BASE 0x4E -#define REG_TEMP_MAX_BASE 0x4F - -#define REG_TACH_MIN_BASE 0x54 - -#define REG_PWM_CONFIG_BASE 0x5C - -#define REG_TEMP_TRANGE_BASE 0x5F - -#define REG_PWM_MIN_BASE 0x64 - -#define REG_TEMP_TMIN_BASE 0x67 -#define REG_TEMP_THERM_BASE 0x6A - -#define REG_REMOTE1_HYSTERSIS 0x6D -#define REG_REMOTE2_HYSTERSIS 0x6E - -#define REG_TEMP_OFFSET_BASE 0x70 - -#define REG_CONFIG2 0x73 - -#define REG_EXTEND1 0x76 -#define REG_EXTEND2 0x77 - -#define REG_CONFIG3 0x78 -#define REG_CONFIG5 0x7C -#define REG_CONFIG4 0x7D - -#define REG_STATUS4 0x81 /* ADT7490 only */ - -#define REG_VTT_MIN 0x84 /* ADT7490 only */ -#define REG_VTT_MAX 0x86 /* ADT7490 only */ - -#define VID_VIDSEL 0x80 /* ADT7476 only */ - -#define CONFIG2_ATTN 0x20 - -#define CONFIG3_SMBALERT 0x01 -#define CONFIG3_THERM 0x02 - -#define CONFIG4_PINFUNC 0x03 -#define CONFIG4_MAXDUTY 0x08 -#define CONFIG4_ATTN_IN10 0x30 -#define CONFIG4_ATTN_IN43 0xC0 - -#define CONFIG5_TWOSCOMP 0x01 -#define CONFIG5_TEMPOFFSET 0x02 -#define CONFIG5_VIDGPIO 0x10 /* ADT7476 only */ - -/* ADT7475 Settings */ - -#define ADT7475_VOLTAGE_COUNT 5 /* Not counting Vtt */ -#define ADT7475_TEMP_COUNT 3 -#define ADT7475_TACH_COUNT 4 -#define ADT7475_PWM_COUNT 3 - -/* Macro to read the registers */ - -#define adt7475_read(reg) i2c_smbus_read_byte_data(client, (reg)) - -/* Macros to easily index the registers */ - -#define TACH_REG(idx) (REG_TACH_BASE + ((idx) * 2)) -#define TACH_MIN_REG(idx) (REG_TACH_MIN_BASE + ((idx) * 2)) - -#define PWM_REG(idx) (REG_PWM_BASE + (idx)) -#define PWM_MAX_REG(idx) (REG_PWM_MAX_BASE + (idx)) -#define PWM_MIN_REG(idx) (REG_PWM_MIN_BASE + (idx)) -#define PWM_CONFIG_REG(idx) (REG_PWM_CONFIG_BASE + (idx)) - -#define VOLTAGE_REG(idx) (REG_VOLTAGE_BASE + (idx)) -#define VOLTAGE_MIN_REG(idx) (REG_VOLTAGE_MIN_BASE + ((idx) * 2)) -#define VOLTAGE_MAX_REG(idx) (REG_VOLTAGE_MAX_BASE + ((idx) * 2)) - -#define TEMP_REG(idx) (REG_TEMP_BASE + (idx)) -#define TEMP_MIN_REG(idx) (REG_TEMP_MIN_BASE + ((idx) * 2)) -#define TEMP_MAX_REG(idx) (REG_TEMP_MAX_BASE + ((idx) * 2)) -#define TEMP_TMIN_REG(idx) (REG_TEMP_TMIN_BASE + (idx)) -#define TEMP_THERM_REG(idx) (REG_TEMP_THERM_BASE + (idx)) -#define TEMP_OFFSET_REG(idx) (REG_TEMP_OFFSET_BASE + (idx)) -#define TEMP_TRANGE_REG(idx) (REG_TEMP_TRANGE_BASE + (idx)) - -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -enum chips { adt7473, adt7475, adt7476, adt7490 }; - -static const struct i2c_device_id adt7475_id[] = { - { "adt7473", adt7473 }, - { "adt7475", adt7475 }, - { "adt7476", adt7476 }, - { "adt7490", adt7490 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7475_id); - -struct adt7475_data { - struct device *hwmon_dev; - struct mutex lock; - - unsigned long measure_updated; - unsigned long limits_updated; - char valid; - - u8 config4; - u8 config5; - u8 has_voltage; - u8 bypass_attn; /* Bypass voltage attenuator */ - u8 has_pwm2:1; - u8 has_fan4:1; - u8 has_vid:1; - u32 alarms; - u16 voltage[3][6]; - u16 temp[7][3]; - u16 tach[2][4]; - u8 pwm[4][3]; - u8 range[3]; - u8 pwmctl[3]; - u8 pwmchan[3]; - - u8 vid; - u8 vrm; -}; - -static struct i2c_driver adt7475_driver; -static struct adt7475_data *adt7475_update_device(struct device *dev); -static void adt7475_read_hystersis(struct i2c_client *client); -static void adt7475_read_pwm(struct i2c_client *client, int index); - -/* Given a temp value, convert it to register value */ - -static inline u16 temp2reg(struct adt7475_data *data, long val) -{ - u16 ret; - - if (!(data->config5 & CONFIG5_TWOSCOMP)) { - val = SENSORS_LIMIT(val, -64000, 191000); - ret = (val + 64500) / 1000; - } else { - val = SENSORS_LIMIT(val, -128000, 127000); - if (val < -500) - ret = (256500 + val) / 1000; - else - ret = (val + 500) / 1000; - } - - return ret << 2; -} - -/* Given a register value, convert it to a real temp value */ - -static inline int reg2temp(struct adt7475_data *data, u16 reg) -{ - if (data->config5 & CONFIG5_TWOSCOMP) { - if (reg >= 512) - return (reg - 1024) * 250; - else - return reg * 250; - } else - return (reg - 256) * 250; -} - -static inline int tach2rpm(u16 tach) -{ - if (tach == 0 || tach == 0xFFFF) - return 0; - - return (90000 * 60) / tach; -} - -static inline u16 rpm2tach(unsigned long rpm) -{ - if (rpm == 0) - return 0; - - return SENSORS_LIMIT((90000 * 60) / rpm, 1, 0xFFFF); -} - -/* Scaling factors for voltage inputs, taken from the ADT7490 datasheet */ -static const int adt7473_in_scaling[ADT7475_VOLTAGE_COUNT + 1][2] = { - { 45, 94 }, /* +2.5V */ - { 175, 525 }, /* Vccp */ - { 68, 71 }, /* Vcc */ - { 93, 47 }, /* +5V */ - { 120, 20 }, /* +12V */ - { 45, 45 }, /* Vtt */ -}; - -static inline int reg2volt(int channel, u16 reg, u8 bypass_attn) -{ - const int *r = adt7473_in_scaling[channel]; - - if (bypass_attn & (1 << channel)) - return DIV_ROUND_CLOSEST(reg * 2250, 1024); - return DIV_ROUND_CLOSEST(reg * (r[0] + r[1]) * 2250, r[1] * 1024); -} - -static inline u16 volt2reg(int channel, long volt, u8 bypass_attn) -{ - const int *r = adt7473_in_scaling[channel]; - long reg; - - if (bypass_attn & (1 << channel)) - reg = (volt * 1024) / 2250; - else - reg = (volt * r[1] * 1024) / ((r[0] + r[1]) * 2250); - return SENSORS_LIMIT(reg, 0, 1023) & (0xff << 2); -} - -static u16 adt7475_read_word(struct i2c_client *client, int reg) -{ - u16 val; - - val = i2c_smbus_read_byte_data(client, reg); - val |= (i2c_smbus_read_byte_data(client, reg + 1) << 8); - - return val; -} - -static void adt7475_write_word(struct i2c_client *client, int reg, u16 val) -{ - i2c_smbus_write_byte_data(client, reg + 1, val >> 8); - i2c_smbus_write_byte_data(client, reg, val & 0xFF); -} - -/* - * Find the nearest value in a table - used for pwm frequency and - * auto temp range - */ -static int find_nearest(long val, const int *array, int size) -{ - int i; - - if (val < array[0]) - return 0; - - if (val > array[size - 1]) - return size - 1; - - for (i = 0; i < size - 1; i++) { - int a, b; - - if (val > array[i + 1]) - continue; - - a = val - array[i]; - b = array[i + 1] - val; - - return (a <= b) ? i : i + 1; - } - - return 0; -} - -static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - unsigned short val; - - switch (sattr->nr) { - case ALARM: - return sprintf(buf, "%d\n", - (data->alarms >> sattr->index) & 1); - default: - val = data->voltage[sattr->nr][sattr->index]; - return sprintf(buf, "%d\n", - reg2volt(sattr->index, val, data->bypass_attn)); - } -} - -static ssize_t set_voltage(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - unsigned char reg; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - data->voltage[sattr->nr][sattr->index] = - volt2reg(sattr->index, val, data->bypass_attn); - - if (sattr->index < ADT7475_VOLTAGE_COUNT) { - if (sattr->nr == MIN) - reg = VOLTAGE_MIN_REG(sattr->index); - else - reg = VOLTAGE_MAX_REG(sattr->index); - } else { - if (sattr->nr == MIN) - reg = REG_VTT_MIN; - else - reg = REG_VTT_MAX; - } - - i2c_smbus_write_byte_data(client, reg, - data->voltage[sattr->nr][sattr->index] >> 2); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int out; - - switch (sattr->nr) { - case HYSTERSIS: - mutex_lock(&data->lock); - out = data->temp[sattr->nr][sattr->index]; - if (sattr->index != 1) - out = (out >> 4) & 0xF; - else - out = (out & 0xF); - /* - * Show the value as an absolute number tied to - * THERM - */ - out = reg2temp(data, data->temp[THERM][sattr->index]) - - out * 1000; - mutex_unlock(&data->lock); - break; - - case OFFSET: - /* - * Offset is always 2's complement, regardless of the - * setting in CONFIG5 - */ - mutex_lock(&data->lock); - out = (s8)data->temp[sattr->nr][sattr->index]; - if (data->config5 & CONFIG5_TEMPOFFSET) - out *= 1000; - else - out *= 500; - mutex_unlock(&data->lock); - break; - - case ALARM: - out = (data->alarms >> (sattr->index + 4)) & 1; - break; - - case FAULT: - /* Note - only for remote1 and remote2 */ - out = !!(data->alarms & (sattr->index ? 0x8000 : 0x4000)); - break; - - default: - /* All other temp values are in the configured format */ - out = reg2temp(data, data->temp[sattr->nr][sattr->index]); - } - - return sprintf(buf, "%d\n", out); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - unsigned char reg = 0; - u8 out; - int temp; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - /* We need the config register in all cases for temp <-> reg conv. */ - data->config5 = adt7475_read(REG_CONFIG5); - - switch (sattr->nr) { - case OFFSET: - if (data->config5 & CONFIG5_TEMPOFFSET) { - val = SENSORS_LIMIT(val, -63000, 127000); - out = data->temp[OFFSET][sattr->index] = val / 1000; - } else { - val = SENSORS_LIMIT(val, -63000, 64000); - out = data->temp[OFFSET][sattr->index] = val / 500; - } - break; - - case HYSTERSIS: - /* - * The value will be given as an absolute value, turn it - * into an offset based on THERM - */ - - /* Read fresh THERM and HYSTERSIS values from the chip */ - data->temp[THERM][sattr->index] = - adt7475_read(TEMP_THERM_REG(sattr->index)) << 2; - adt7475_read_hystersis(client); - - temp = reg2temp(data, data->temp[THERM][sattr->index]); - val = SENSORS_LIMIT(val, temp - 15000, temp); - val = (temp - val) / 1000; - - if (sattr->index != 1) { - data->temp[HYSTERSIS][sattr->index] &= 0xF0; - data->temp[HYSTERSIS][sattr->index] |= (val & 0xF) << 4; - } else { - data->temp[HYSTERSIS][sattr->index] &= 0x0F; - data->temp[HYSTERSIS][sattr->index] |= (val & 0xF); - } - - out = data->temp[HYSTERSIS][sattr->index]; - break; - - default: - data->temp[sattr->nr][sattr->index] = temp2reg(data, val); - - /* - * We maintain an extra 2 digits of precision for simplicity - * - shift those back off before writing the value - */ - out = (u8) (data->temp[sattr->nr][sattr->index] >> 2); - } - - switch (sattr->nr) { - case MIN: - reg = TEMP_MIN_REG(sattr->index); - break; - case MAX: - reg = TEMP_MAX_REG(sattr->index); - break; - case OFFSET: - reg = TEMP_OFFSET_REG(sattr->index); - break; - case AUTOMIN: - reg = TEMP_TMIN_REG(sattr->index); - break; - case THERM: - reg = TEMP_THERM_REG(sattr->index); - break; - case HYSTERSIS: - if (sattr->index != 2) - reg = REG_REMOTE1_HYSTERSIS; - else - reg = REG_REMOTE2_HYSTERSIS; - - break; - } - - i2c_smbus_write_byte_data(client, reg, out); - - mutex_unlock(&data->lock); - return count; -} - -/* - * Table of autorange values - the user will write the value in millidegrees, - * and we'll convert it - */ -static const int autorange_table[] = { - 2000, 2500, 3330, 4000, 5000, 6670, 8000, - 10000, 13330, 16000, 20000, 26670, 32000, 40000, - 53330, 80000 -}; - -static ssize_t show_point2(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int out, val; - - mutex_lock(&data->lock); - out = (data->range[sattr->index] >> 4) & 0x0F; - val = reg2temp(data, data->temp[AUTOMIN][sattr->index]); - mutex_unlock(&data->lock); - - return sprintf(buf, "%d\n", val + autorange_table[out]); -} - -static ssize_t set_point2(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int temp; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - /* Get a fresh copy of the needed registers */ - data->config5 = adt7475_read(REG_CONFIG5); - data->temp[AUTOMIN][sattr->index] = - adt7475_read(TEMP_TMIN_REG(sattr->index)) << 2; - data->range[sattr->index] = - adt7475_read(TEMP_TRANGE_REG(sattr->index)); - - /* - * The user will write an absolute value, so subtract the start point - * to figure the range - */ - temp = reg2temp(data, data->temp[AUTOMIN][sattr->index]); - val = SENSORS_LIMIT(val, temp + autorange_table[0], - temp + autorange_table[ARRAY_SIZE(autorange_table) - 1]); - val -= temp; - - /* Find the nearest table entry to what the user wrote */ - val = find_nearest(val, autorange_table, ARRAY_SIZE(autorange_table)); - - data->range[sattr->index] &= ~0xF0; - data->range[sattr->index] |= val << 4; - - i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index), - data->range[sattr->index]); - - mutex_unlock(&data->lock); - return count; -} - -static ssize_t show_tach(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - int out; - - if (sattr->nr == ALARM) - out = (data->alarms >> (sattr->index + 10)) & 1; - else - out = tach2rpm(data->tach[sattr->nr][sattr->index]); - - return sprintf(buf, "%d\n", out); -} - -static ssize_t set_tach(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - data->tach[MIN][sattr->index] = rpm2tach(val); - - adt7475_write_word(client, TACH_MIN_REG(sattr->index), - data->tach[MIN][sattr->index]); - - mutex_unlock(&data->lock); - return count; -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - - return sprintf(buf, "%d\n", data->pwm[sattr->nr][sattr->index]); -} - -static ssize_t show_pwmchan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - - return sprintf(buf, "%d\n", data->pwmchan[sattr->index]); -} - -static ssize_t show_pwmctrl(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - - return sprintf(buf, "%d\n", data->pwmctl[sattr->index]); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - unsigned char reg = 0; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - - switch (sattr->nr) { - case INPUT: - /* Get a fresh value for CONTROL */ - data->pwm[CONTROL][sattr->index] = - adt7475_read(PWM_CONFIG_REG(sattr->index)); - - /* - * If we are not in manual mode, then we shouldn't allow - * the user to set the pwm speed - */ - if (((data->pwm[CONTROL][sattr->index] >> 5) & 7) != 7) { - mutex_unlock(&data->lock); - return count; - } - - reg = PWM_REG(sattr->index); - break; - - case MIN: - reg = PWM_MIN_REG(sattr->index); - break; - - case MAX: - reg = PWM_MAX_REG(sattr->index); - break; - } - - data->pwm[sattr->nr][sattr->index] = SENSORS_LIMIT(val, 0, 0xFF); - i2c_smbus_write_byte_data(client, reg, - data->pwm[sattr->nr][sattr->index]); - - mutex_unlock(&data->lock); - - return count; -} - -/* Called by set_pwmctrl and set_pwmchan */ - -static int hw_set_pwm(struct i2c_client *client, int index, - unsigned int pwmctl, unsigned int pwmchan) -{ - struct adt7475_data *data = i2c_get_clientdata(client); - long val = 0; - - switch (pwmctl) { - case 0: - val = 0x03; /* Run at full speed */ - break; - case 1: - val = 0x07; /* Manual mode */ - break; - case 2: - switch (pwmchan) { - case 1: - /* Remote1 controls PWM */ - val = 0x00; - break; - case 2: - /* local controls PWM */ - val = 0x01; - break; - case 4: - /* remote2 controls PWM */ - val = 0x02; - break; - case 6: - /* local/remote2 control PWM */ - val = 0x05; - break; - case 7: - /* All three control PWM */ - val = 0x06; - break; - default: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - data->pwmctl[index] = pwmctl; - data->pwmchan[index] = pwmchan; - - data->pwm[CONTROL][index] &= ~0xE0; - data->pwm[CONTROL][index] |= (val & 7) << 5; - - i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), - data->pwm[CONTROL][index]); - - return 0; -} - -static ssize_t set_pwmchan(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - int r; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - /* Read Modify Write PWM values */ - adt7475_read_pwm(client, sattr->index); - r = hw_set_pwm(client, sattr->index, data->pwmctl[sattr->index], val); - if (r) - count = r; - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t set_pwmctrl(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - int r; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->lock); - /* Read Modify Write PWM values */ - adt7475_read_pwm(client, sattr->index); - r = hw_set_pwm(client, sattr->index, val, data->pwmchan[sattr->index]); - if (r) - count = r; - mutex_unlock(&data->lock); - - return count; -} - -/* List of frequencies for the PWM */ -static const int pwmfreq_table[] = { - 11, 14, 22, 29, 35, 44, 58, 88 -}; - -static ssize_t show_pwmfreq(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - - return sprintf(buf, "%d\n", - pwmfreq_table[data->range[sattr->index] & 7]); -} - -static ssize_t set_pwmfreq(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - int out; - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - out = find_nearest(val, pwmfreq_table, ARRAY_SIZE(pwmfreq_table)); - - mutex_lock(&data->lock); - - data->range[sattr->index] = - adt7475_read(TEMP_TRANGE_REG(sattr->index)); - data->range[sattr->index] &= ~7; - data->range[sattr->index] |= out; - - i2c_smbus_write_byte_data(client, TEMP_TRANGE_REG(sattr->index), - data->range[sattr->index]); - - mutex_unlock(&data->lock); - return count; -} - -static ssize_t show_pwm_at_crit(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - return sprintf(buf, "%d\n", !!(data->config4 & CONFIG4_MAXDUTY)); -} - -static ssize_t set_pwm_at_crit(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - if (val != 0 && val != 1) - return -EINVAL; - - mutex_lock(&data->lock); - data->config4 = i2c_smbus_read_byte_data(client, REG_CONFIG4); - if (val) - data->config4 |= CONFIG4_MAXDUTY; - else - data->config4 &= ~CONFIG4_MAXDUTY; - i2c_smbus_write_byte_data(client, REG_CONFIG4, data->config4); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_vrm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct adt7475_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", (int)data->vrm); -} - -static ssize_t set_vrm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct adt7475_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - if (val < 0 || val > 255) - return -EINVAL; - data->vrm = val; - - return count; -} - -static ssize_t show_vid(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct adt7475_data *data = adt7475_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} - -static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_voltage, NULL, INPUT, 0); -static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MAX, 0); -static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MIN, 0); -static SENSOR_DEVICE_ATTR_2(in0_alarm, S_IRUGO, show_voltage, NULL, ALARM, 0); -static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_voltage, NULL, INPUT, 1); -static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MAX, 1); -static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MIN, 1); -static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, show_voltage, NULL, ALARM, 1); -static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_voltage, NULL, INPUT, 2); -static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MAX, 2); -static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MIN, 2); -static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, show_voltage, NULL, ALARM, 2); -static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_voltage, NULL, INPUT, 3); -static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MAX, 3); -static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MIN, 3); -static SENSOR_DEVICE_ATTR_2(in3_alarm, S_IRUGO, show_voltage, NULL, ALARM, 3); -static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_voltage, NULL, INPUT, 4); -static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MAX, 4); -static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MIN, 4); -static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, show_voltage, NULL, ALARM, 8); -static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_voltage, NULL, INPUT, 5); -static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MAX, 5); -static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_voltage, - set_voltage, MIN, 5); -static SENSOR_DEVICE_ATTR_2(in5_alarm, S_IRUGO, show_voltage, NULL, ALARM, 31); -static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, INPUT, 0); -static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, show_temp, NULL, ALARM, 0); -static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, show_temp, NULL, FAULT, 0); -static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - MAX, 0); -static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - MIN, 0); -static SENSOR_DEVICE_ATTR_2(temp1_offset, S_IRUGO | S_IWUSR, show_temp, - set_temp, OFFSET, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO | S_IWUSR, - show_temp, set_temp, AUTOMIN, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IRUGO | S_IWUSR, - show_point2, set_point2, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp1_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, - THERM, 0); -static SENSOR_DEVICE_ATTR_2(temp1_crit_hyst, S_IRUGO | S_IWUSR, show_temp, - set_temp, HYSTERSIS, 0); -static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, INPUT, 1); -static SENSOR_DEVICE_ATTR_2(temp2_alarm, S_IRUGO, show_temp, NULL, ALARM, 1); -static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - MAX, 1); -static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - MIN, 1); -static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IRUGO | S_IWUSR, show_temp, - set_temp, OFFSET, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IRUGO | S_IWUSR, - show_temp, set_temp, AUTOMIN, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IRUGO | S_IWUSR, - show_point2, set_point2, 0, 1); -static SENSOR_DEVICE_ATTR_2(temp2_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, - THERM, 1); -static SENSOR_DEVICE_ATTR_2(temp2_crit_hyst, S_IRUGO | S_IWUSR, show_temp, - set_temp, HYSTERSIS, 1); -static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, INPUT, 2); -static SENSOR_DEVICE_ATTR_2(temp3_alarm, S_IRUGO, show_temp, NULL, ALARM, 2); -static SENSOR_DEVICE_ATTR_2(temp3_fault, S_IRUGO, show_temp, NULL, FAULT, 2); -static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - MAX, 2); -static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - MIN, 2); -static SENSOR_DEVICE_ATTR_2(temp3_offset, S_IRUGO | S_IWUSR, show_temp, - set_temp, OFFSET, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_point1_temp, S_IRUGO | S_IWUSR, - show_temp, set_temp, AUTOMIN, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_point2_temp, S_IRUGO | S_IWUSR, - show_point2, set_point2, 0, 2); -static SENSOR_DEVICE_ATTR_2(temp3_crit, S_IRUGO | S_IWUSR, show_temp, set_temp, - THERM, 2); -static SENSOR_DEVICE_ATTR_2(temp3_crit_hyst, S_IRUGO | S_IWUSR, show_temp, - set_temp, HYSTERSIS, 2); -static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_tach, NULL, INPUT, 0); -static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_tach, set_tach, - MIN, 0); -static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, show_tach, NULL, ALARM, 0); -static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_tach, NULL, INPUT, 1); -static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_tach, set_tach, - MIN, 1); -static SENSOR_DEVICE_ATTR_2(fan2_alarm, S_IRUGO, show_tach, NULL, ALARM, 1); -static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_tach, NULL, INPUT, 2); -static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_tach, set_tach, - MIN, 2); -static SENSOR_DEVICE_ATTR_2(fan3_alarm, S_IRUGO, show_tach, NULL, ALARM, 2); -static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_tach, NULL, INPUT, 3); -static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_tach, set_tach, - MIN, 3); -static SENSOR_DEVICE_ATTR_2(fan4_alarm, S_IRUGO, show_tach, NULL, ALARM, 3); -static SENSOR_DEVICE_ATTR_2(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, - 0); -static SENSOR_DEVICE_ATTR_2(pwm1_freq, S_IRUGO | S_IWUSR, show_pwmfreq, - set_pwmfreq, INPUT, 0); -static SENSOR_DEVICE_ATTR_2(pwm1_enable, S_IRUGO | S_IWUSR, show_pwmctrl, - set_pwmctrl, INPUT, 0); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_channels_temp, S_IRUGO | S_IWUSR, - show_pwmchan, set_pwmchan, INPUT, 0); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, - set_pwm, MIN, 0); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, - set_pwm, MAX, 0); -static SENSOR_DEVICE_ATTR_2(pwm2, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, - 1); -static SENSOR_DEVICE_ATTR_2(pwm2_freq, S_IRUGO | S_IWUSR, show_pwmfreq, - set_pwmfreq, INPUT, 1); -static SENSOR_DEVICE_ATTR_2(pwm2_enable, S_IRUGO | S_IWUSR, show_pwmctrl, - set_pwmctrl, INPUT, 1); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_channels_temp, S_IRUGO | S_IWUSR, - show_pwmchan, set_pwmchan, INPUT, 1); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, - set_pwm, MIN, 1); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, - set_pwm, MAX, 1); -static SENSOR_DEVICE_ATTR_2(pwm3, S_IRUGO | S_IWUSR, show_pwm, set_pwm, INPUT, - 2); -static SENSOR_DEVICE_ATTR_2(pwm3_freq, S_IRUGO | S_IWUSR, show_pwmfreq, - set_pwmfreq, INPUT, 2); -static SENSOR_DEVICE_ATTR_2(pwm3_enable, S_IRUGO | S_IWUSR, show_pwmctrl, - set_pwmctrl, INPUT, 2); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_channels_temp, S_IRUGO | S_IWUSR, - show_pwmchan, set_pwmchan, INPUT, 2); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO | S_IWUSR, show_pwm, - set_pwm, MIN, 2); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO | S_IWUSR, show_pwm, - set_pwm, MAX, 2); - -/* Non-standard name, might need revisiting */ -static DEVICE_ATTR(pwm_use_point2_pwm_at_crit, S_IWUSR | S_IRUGO, - show_pwm_at_crit, set_pwm_at_crit); - -static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, set_vrm); -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -static struct attribute *adt7475_attrs[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, - &dev_attr_pwm_use_point2_pwm_at_crit.attr, - NULL, -}; - -static struct attribute *fan4_attrs[] = { - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *pwm2_attrs[] = { - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, - NULL -}; - -static struct attribute *in0_attrs[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in3_attrs[] = { - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in4_attrs[] = { - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *in5_attrs[] = { - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *vid_attrs[] = { - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - NULL -}; - -static struct attribute_group adt7475_attr_group = { .attrs = adt7475_attrs }; -static struct attribute_group fan4_attr_group = { .attrs = fan4_attrs }; -static struct attribute_group pwm2_attr_group = { .attrs = pwm2_attrs }; -static struct attribute_group in0_attr_group = { .attrs = in0_attrs }; -static struct attribute_group in3_attr_group = { .attrs = in3_attrs }; -static struct attribute_group in4_attr_group = { .attrs = in4_attrs }; -static struct attribute_group in5_attr_group = { .attrs = in5_attrs }; -static struct attribute_group vid_attr_group = { .attrs = vid_attrs }; - -static int adt7475_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int vendid, devid, devid2; - const char *name; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - vendid = adt7475_read(REG_VENDID); - devid2 = adt7475_read(REG_DEVID2); - if (vendid != 0x41 || /* Analog Devices */ - (devid2 & 0xf8) != 0x68) - return -ENODEV; - - devid = adt7475_read(REG_DEVID); - if (devid == 0x73) - name = "adt7473"; - else if (devid == 0x75 && client->addr == 0x2e) - name = "adt7475"; - else if (devid == 0x76) - name = "adt7476"; - else if ((devid2 & 0xfc) == 0x6c) - name = "adt7490"; - else { - dev_dbg(&adapter->dev, - "Couldn't detect an ADT7473/75/76/90 part at " - "0x%02x\n", (unsigned int)client->addr); - return -ENODEV; - } - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static void adt7475_remove_files(struct i2c_client *client, - struct adt7475_data *data) -{ - sysfs_remove_group(&client->dev.kobj, &adt7475_attr_group); - if (data->has_fan4) - sysfs_remove_group(&client->dev.kobj, &fan4_attr_group); - if (data->has_pwm2) - sysfs_remove_group(&client->dev.kobj, &pwm2_attr_group); - if (data->has_voltage & (1 << 0)) - sysfs_remove_group(&client->dev.kobj, &in0_attr_group); - if (data->has_voltage & (1 << 3)) - sysfs_remove_group(&client->dev.kobj, &in3_attr_group); - if (data->has_voltage & (1 << 4)) - sysfs_remove_group(&client->dev.kobj, &in4_attr_group); - if (data->has_voltage & (1 << 5)) - sysfs_remove_group(&client->dev.kobj, &in5_attr_group); - if (data->has_vid) - sysfs_remove_group(&client->dev.kobj, &vid_attr_group); -} - -static int adt7475_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - static const char * const names[] = { - [adt7473] = "ADT7473", - [adt7475] = "ADT7475", - [adt7476] = "ADT7476", - [adt7490] = "ADT7490", - }; - - struct adt7475_data *data; - int i, ret = 0, revision; - u8 config2, config3; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - mutex_init(&data->lock); - i2c_set_clientdata(client, data); - - /* Initialize device-specific values */ - switch (id->driver_data) { - case adt7476: - data->has_voltage = 0x0e; /* in1 to in3 */ - revision = adt7475_read(REG_DEVID2) & 0x07; - break; - case adt7490: - data->has_voltage = 0x3e; /* in1 to in5 */ - revision = adt7475_read(REG_DEVID2) & 0x03; - if (revision == 0x03) - revision += adt7475_read(REG_DEVREV2); - break; - default: - data->has_voltage = 0x06; /* in1, in2 */ - revision = adt7475_read(REG_DEVID2) & 0x07; - } - - config3 = adt7475_read(REG_CONFIG3); - /* Pin PWM2 may alternatively be used for ALERT output */ - if (!(config3 & CONFIG3_SMBALERT)) - data->has_pwm2 = 1; - /* Meaning of this bit is inverted for the ADT7473-1 */ - if (id->driver_data == adt7473 && revision >= 1) - data->has_pwm2 = !data->has_pwm2; - - data->config4 = adt7475_read(REG_CONFIG4); - /* Pin TACH4 may alternatively be used for THERM */ - if ((data->config4 & CONFIG4_PINFUNC) == 0x0) - data->has_fan4 = 1; - - /* - * THERM configuration is more complex on the ADT7476 and ADT7490, - * because 2 different pins (TACH4 and +2.5 Vin) can be used for - * this function - */ - if (id->driver_data == adt7490) { - if ((data->config4 & CONFIG4_PINFUNC) == 0x1 && - !(config3 & CONFIG3_THERM)) - data->has_fan4 = 1; - } - if (id->driver_data == adt7476 || id->driver_data == adt7490) { - if (!(config3 & CONFIG3_THERM) || - (data->config4 & CONFIG4_PINFUNC) == 0x1) - data->has_voltage |= (1 << 0); /* in0 */ - } - - /* - * On the ADT7476, the +12V input pin may instead be used as VID5, - * and VID pins may alternatively be used as GPIO - */ - if (id->driver_data == adt7476) { - u8 vid = adt7475_read(REG_VID); - if (!(vid & VID_VIDSEL)) - data->has_voltage |= (1 << 4); /* in4 */ - - data->has_vid = !(adt7475_read(REG_CONFIG5) & CONFIG5_VIDGPIO); - } - - /* Voltage attenuators can be bypassed, globally or individually */ - config2 = adt7475_read(REG_CONFIG2); - if (config2 & CONFIG2_ATTN) { - data->bypass_attn = (0x3 << 3) | 0x3; - } else { - data->bypass_attn = ((data->config4 & CONFIG4_ATTN_IN10) >> 4) | - ((data->config4 & CONFIG4_ATTN_IN43) >> 3); - } - data->bypass_attn &= data->has_voltage; - - /* - * Call adt7475_read_pwm for all pwm's as this will reprogram any - * pwm's which are disabled to manual mode with 0% duty cycle - */ - for (i = 0; i < ADT7475_PWM_COUNT; i++) - adt7475_read_pwm(client, i); - - ret = sysfs_create_group(&client->dev.kobj, &adt7475_attr_group); - if (ret) - goto efree; - - /* Features that can be disabled individually */ - if (data->has_fan4) { - ret = sysfs_create_group(&client->dev.kobj, &fan4_attr_group); - if (ret) - goto eremove; - } - if (data->has_pwm2) { - ret = sysfs_create_group(&client->dev.kobj, &pwm2_attr_group); - if (ret) - goto eremove; - } - if (data->has_voltage & (1 << 0)) { - ret = sysfs_create_group(&client->dev.kobj, &in0_attr_group); - if (ret) - goto eremove; - } - if (data->has_voltage & (1 << 3)) { - ret = sysfs_create_group(&client->dev.kobj, &in3_attr_group); - if (ret) - goto eremove; - } - if (data->has_voltage & (1 << 4)) { - ret = sysfs_create_group(&client->dev.kobj, &in4_attr_group); - if (ret) - goto eremove; - } - if (data->has_voltage & (1 << 5)) { - ret = sysfs_create_group(&client->dev.kobj, &in5_attr_group); - if (ret) - goto eremove; - } - if (data->has_vid) { - data->vrm = vid_which_vrm(); - ret = sysfs_create_group(&client->dev.kobj, &vid_attr_group); - if (ret) - goto eremove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto eremove; - } - - dev_info(&client->dev, "%s device, revision %d\n", - names[id->driver_data], revision); - if ((data->has_voltage & 0x11) || data->has_fan4 || data->has_pwm2) - dev_info(&client->dev, "Optional features:%s%s%s%s%s\n", - (data->has_voltage & (1 << 0)) ? " in0" : "", - (data->has_voltage & (1 << 4)) ? " in4" : "", - data->has_fan4 ? " fan4" : "", - data->has_pwm2 ? " pwm2" : "", - data->has_vid ? " vid" : ""); - if (data->bypass_attn) - dev_info(&client->dev, "Bypassing attenuators on:%s%s%s%s\n", - (data->bypass_attn & (1 << 0)) ? " in0" : "", - (data->bypass_attn & (1 << 1)) ? " in1" : "", - (data->bypass_attn & (1 << 3)) ? " in3" : "", - (data->bypass_attn & (1 << 4)) ? " in4" : ""); - - return 0; - -eremove: - adt7475_remove_files(client, data); -efree: - kfree(data); - return ret; -} - -static int adt7475_remove(struct i2c_client *client) -{ - struct adt7475_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - adt7475_remove_files(client, data); - kfree(data); - - return 0; -} - -static struct i2c_driver adt7475_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adt7475", - }, - .probe = adt7475_probe, - .remove = adt7475_remove, - .id_table = adt7475_id, - .detect = adt7475_detect, - .address_list = normal_i2c, -}; - -static void adt7475_read_hystersis(struct i2c_client *client) -{ - struct adt7475_data *data = i2c_get_clientdata(client); - - data->temp[HYSTERSIS][0] = (u16) adt7475_read(REG_REMOTE1_HYSTERSIS); - data->temp[HYSTERSIS][1] = data->temp[HYSTERSIS][0]; - data->temp[HYSTERSIS][2] = (u16) adt7475_read(REG_REMOTE2_HYSTERSIS); -} - -static void adt7475_read_pwm(struct i2c_client *client, int index) -{ - struct adt7475_data *data = i2c_get_clientdata(client); - unsigned int v; - - data->pwm[CONTROL][index] = adt7475_read(PWM_CONFIG_REG(index)); - - /* - * Figure out the internal value for pwmctrl and pwmchan - * based on the current settings - */ - v = (data->pwm[CONTROL][index] >> 5) & 7; - - if (v == 3) - data->pwmctl[index] = 0; - else if (v == 7) - data->pwmctl[index] = 1; - else if (v == 4) { - /* - * The fan is disabled - we don't want to - * support that, so change to manual mode and - * set the duty cycle to 0 instead - */ - data->pwm[INPUT][index] = 0; - data->pwm[CONTROL][index] &= ~0xE0; - data->pwm[CONTROL][index] |= (7 << 5); - - i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), - data->pwm[INPUT][index]); - - i2c_smbus_write_byte_data(client, PWM_CONFIG_REG(index), - data->pwm[CONTROL][index]); - - data->pwmctl[index] = 1; - } else { - data->pwmctl[index] = 2; - - switch (v) { - case 0: - data->pwmchan[index] = 1; - break; - case 1: - data->pwmchan[index] = 2; - break; - case 2: - data->pwmchan[index] = 4; - break; - case 5: - data->pwmchan[index] = 6; - break; - case 6: - data->pwmchan[index] = 7; - break; - } - } -} - -static struct adt7475_data *adt7475_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adt7475_data *data = i2c_get_clientdata(client); - u16 ext; - int i; - - mutex_lock(&data->lock); - - /* Measurement values update every 2 seconds */ - if (time_after(jiffies, data->measure_updated + HZ * 2) || - !data->valid) { - data->alarms = adt7475_read(REG_STATUS2) << 8; - data->alarms |= adt7475_read(REG_STATUS1); - - ext = (adt7475_read(REG_EXTEND2) << 8) | - adt7475_read(REG_EXTEND1); - for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) { - if (!(data->has_voltage & (1 << i))) - continue; - data->voltage[INPUT][i] = - (adt7475_read(VOLTAGE_REG(i)) << 2) | - ((ext >> (i * 2)) & 3); - } - - for (i = 0; i < ADT7475_TEMP_COUNT; i++) - data->temp[INPUT][i] = - (adt7475_read(TEMP_REG(i)) << 2) | - ((ext >> ((i + 5) * 2)) & 3); - - if (data->has_voltage & (1 << 5)) { - data->alarms |= adt7475_read(REG_STATUS4) << 24; - ext = adt7475_read(REG_EXTEND3); - data->voltage[INPUT][5] = adt7475_read(REG_VTT) << 2 | - ((ext >> 4) & 3); - } - - for (i = 0; i < ADT7475_TACH_COUNT; i++) { - if (i == 3 && !data->has_fan4) - continue; - data->tach[INPUT][i] = - adt7475_read_word(client, TACH_REG(i)); - } - - /* Updated by hw when in auto mode */ - for (i = 0; i < ADT7475_PWM_COUNT; i++) { - if (i == 1 && !data->has_pwm2) - continue; - data->pwm[INPUT][i] = adt7475_read(PWM_REG(i)); - } - - if (data->has_vid) - data->vid = adt7475_read(REG_VID) & 0x3f; - - data->measure_updated = jiffies; - } - - /* Limits and settings, should never change update every 60 seconds */ - if (time_after(jiffies, data->limits_updated + HZ * 60) || - !data->valid) { - data->config4 = adt7475_read(REG_CONFIG4); - data->config5 = adt7475_read(REG_CONFIG5); - - for (i = 0; i < ADT7475_VOLTAGE_COUNT; i++) { - if (!(data->has_voltage & (1 << i))) - continue; - /* Adjust values so they match the input precision */ - data->voltage[MIN][i] = - adt7475_read(VOLTAGE_MIN_REG(i)) << 2; - data->voltage[MAX][i] = - adt7475_read(VOLTAGE_MAX_REG(i)) << 2; - } - - if (data->has_voltage & (1 << 5)) { - data->voltage[MIN][5] = adt7475_read(REG_VTT_MIN) << 2; - data->voltage[MAX][5] = adt7475_read(REG_VTT_MAX) << 2; - } - - for (i = 0; i < ADT7475_TEMP_COUNT; i++) { - /* Adjust values so they match the input precision */ - data->temp[MIN][i] = - adt7475_read(TEMP_MIN_REG(i)) << 2; - data->temp[MAX][i] = - adt7475_read(TEMP_MAX_REG(i)) << 2; - data->temp[AUTOMIN][i] = - adt7475_read(TEMP_TMIN_REG(i)) << 2; - data->temp[THERM][i] = - adt7475_read(TEMP_THERM_REG(i)) << 2; - data->temp[OFFSET][i] = - adt7475_read(TEMP_OFFSET_REG(i)); - } - adt7475_read_hystersis(client); - - for (i = 0; i < ADT7475_TACH_COUNT; i++) { - if (i == 3 && !data->has_fan4) - continue; - data->tach[MIN][i] = - adt7475_read_word(client, TACH_MIN_REG(i)); - } - - for (i = 0; i < ADT7475_PWM_COUNT; i++) { - if (i == 1 && !data->has_pwm2) - continue; - data->pwm[MAX][i] = adt7475_read(PWM_MAX_REG(i)); - data->pwm[MIN][i] = adt7475_read(PWM_MIN_REG(i)); - /* Set the channel and control information */ - adt7475_read_pwm(client, i); - } - - data->range[0] = adt7475_read(TEMP_TRANGE_REG(0)); - data->range[1] = adt7475_read(TEMP_TRANGE_REG(1)); - data->range[2] = adt7475_read(TEMP_TRANGE_REG(2)); - - data->limits_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->lock); - - return data; -} - -module_i2c_driver(adt7475_driver); - -MODULE_AUTHOR("Advanced Micro Devices, Inc"); -MODULE_DESCRIPTION("adt7475 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/amc6821.c b/ANDROID_3.4.5/drivers/hwmon/amc6821.c deleted file mode 100644 index f600fa1f..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/amc6821.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * amc6821.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2009 T. Mertelj - * - * Based on max6650.c: - * Copyright (C) 2007 Hans J. Koch - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include /* Needed for KERN_INFO */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * Addresses to scan. - */ - -static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, - 0x4c, 0x4d, 0x4e, I2C_CLIENT_END}; - - - -/* - * Insmod parameters - */ - -static int pwminv; /*Inverted PWM output. */ -module_param(pwminv, int, S_IRUGO); - -static int init = 1; /*Power-on initialization.*/ -module_param(init, int, S_IRUGO); - - -enum chips { amc6821 }; - -#define AMC6821_REG_DEV_ID 0x3D -#define AMC6821_REG_COMP_ID 0x3E -#define AMC6821_REG_CONF1 0x00 -#define AMC6821_REG_CONF2 0x01 -#define AMC6821_REG_CONF3 0x3F -#define AMC6821_REG_CONF4 0x04 -#define AMC6821_REG_STAT1 0x02 -#define AMC6821_REG_STAT2 0x03 -#define AMC6821_REG_TDATA_LOW 0x08 -#define AMC6821_REG_TDATA_HI 0x09 -#define AMC6821_REG_LTEMP_HI 0x0A -#define AMC6821_REG_RTEMP_HI 0x0B -#define AMC6821_REG_LTEMP_LIMIT_MIN 0x15 -#define AMC6821_REG_LTEMP_LIMIT_MAX 0x14 -#define AMC6821_REG_RTEMP_LIMIT_MIN 0x19 -#define AMC6821_REG_RTEMP_LIMIT_MAX 0x18 -#define AMC6821_REG_LTEMP_CRIT 0x1B -#define AMC6821_REG_RTEMP_CRIT 0x1D -#define AMC6821_REG_PSV_TEMP 0x1C -#define AMC6821_REG_DCY 0x22 -#define AMC6821_REG_LTEMP_FAN_CTRL 0x24 -#define AMC6821_REG_RTEMP_FAN_CTRL 0x25 -#define AMC6821_REG_DCY_LOW_TEMP 0x21 - -#define AMC6821_REG_TACH_LLIMITL 0x10 -#define AMC6821_REG_TACH_LLIMITH 0x11 -#define AMC6821_REG_TACH_HLIMITL 0x12 -#define AMC6821_REG_TACH_HLIMITH 0x13 - -#define AMC6821_CONF1_START 0x01 -#define AMC6821_CONF1_FAN_INT_EN 0x02 -#define AMC6821_CONF1_FANIE 0x04 -#define AMC6821_CONF1_PWMINV 0x08 -#define AMC6821_CONF1_FAN_FAULT_EN 0x10 -#define AMC6821_CONF1_FDRC0 0x20 -#define AMC6821_CONF1_FDRC1 0x40 -#define AMC6821_CONF1_THERMOVIE 0x80 - -#define AMC6821_CONF2_PWM_EN 0x01 -#define AMC6821_CONF2_TACH_MODE 0x02 -#define AMC6821_CONF2_TACH_EN 0x04 -#define AMC6821_CONF2_RTFIE 0x08 -#define AMC6821_CONF2_LTOIE 0x10 -#define AMC6821_CONF2_RTOIE 0x20 -#define AMC6821_CONF2_PSVIE 0x40 -#define AMC6821_CONF2_RST 0x80 - -#define AMC6821_CONF3_THERM_FAN_EN 0x80 -#define AMC6821_CONF3_REV_MASK 0x0F - -#define AMC6821_CONF4_OVREN 0x10 -#define AMC6821_CONF4_TACH_FAST 0x20 -#define AMC6821_CONF4_PSPR 0x40 -#define AMC6821_CONF4_MODE 0x80 - -#define AMC6821_STAT1_RPM_ALARM 0x01 -#define AMC6821_STAT1_FANS 0x02 -#define AMC6821_STAT1_RTH 0x04 -#define AMC6821_STAT1_RTL 0x08 -#define AMC6821_STAT1_R_THERM 0x10 -#define AMC6821_STAT1_RTF 0x20 -#define AMC6821_STAT1_LTH 0x40 -#define AMC6821_STAT1_LTL 0x80 - -#define AMC6821_STAT2_RTC 0x08 -#define AMC6821_STAT2_LTC 0x10 -#define AMC6821_STAT2_LPSV 0x20 -#define AMC6821_STAT2_L_THERM 0x40 -#define AMC6821_STAT2_THERM_IN 0x80 - -enum {IDX_TEMP1_INPUT = 0, IDX_TEMP1_MIN, IDX_TEMP1_MAX, - IDX_TEMP1_CRIT, IDX_TEMP2_INPUT, IDX_TEMP2_MIN, - IDX_TEMP2_MAX, IDX_TEMP2_CRIT, - TEMP_IDX_LEN, }; - -static const u8 temp_reg[] = {AMC6821_REG_LTEMP_HI, - AMC6821_REG_LTEMP_LIMIT_MIN, - AMC6821_REG_LTEMP_LIMIT_MAX, - AMC6821_REG_LTEMP_CRIT, - AMC6821_REG_RTEMP_HI, - AMC6821_REG_RTEMP_LIMIT_MIN, - AMC6821_REG_RTEMP_LIMIT_MAX, - AMC6821_REG_RTEMP_CRIT, }; - -enum {IDX_FAN1_INPUT = 0, IDX_FAN1_MIN, IDX_FAN1_MAX, - FAN1_IDX_LEN, }; - -static const u8 fan_reg_low[] = {AMC6821_REG_TDATA_LOW, - AMC6821_REG_TACH_LLIMITL, - AMC6821_REG_TACH_HLIMITL, }; - - -static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, - AMC6821_REG_TACH_LLIMITH, - AMC6821_REG_TACH_HLIMITH, }; - -static int amc6821_probe( - struct i2c_client *client, - const struct i2c_device_id *id); -static int amc6821_detect( - struct i2c_client *client, - struct i2c_board_info *info); -static int amc6821_init_client(struct i2c_client *client); -static int amc6821_remove(struct i2c_client *client); -static struct amc6821_data *amc6821_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id amc6821_id[] = { - { "amc6821", amc6821 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, amc6821_id); - -static struct i2c_driver amc6821_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "amc6821", - }, - .probe = amc6821_probe, - .remove = amc6821_remove, - .id_table = amc6821_id, - .detect = amc6821_detect, - .address_list = normal_i2c, -}; - - -/* - * Client data (each client gets its own) - */ - -struct amc6821_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* register values */ - int temp[TEMP_IDX_LEN]; - - u16 fan[FAN1_IDX_LEN]; - u8 fan1_div; - - u8 pwm1; - u8 temp1_auto_point_temp[3]; - u8 temp2_auto_point_temp[3]; - u8 pwm1_auto_point_pwm[3]; - u8 pwm1_enable; - u8 pwm1_auto_channels_temp; - - u8 stat1; - u8 stat2; -}; - - -static ssize_t get_temp( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - int ix = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", data->temp[ix] * 1000); -} - - - -static ssize_t set_temp( - struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - int ix = to_sensor_dev_attr(attr)->index; - long val; - - int ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - val = SENSORS_LIMIT(val / 1000, -128, 127); - - mutex_lock(&data->update_lock); - data->temp[ix] = val; - if (i2c_smbus_write_byte_data(client, temp_reg[ix], data->temp[ix])) { - dev_err(&client->dev, "Register write error, aborting.\n"); - count = -EIO; - } - mutex_unlock(&data->update_lock); - return count; -} - - - - -static ssize_t get_temp_alarm( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - int ix = to_sensor_dev_attr(devattr)->index; - u8 flag; - - switch (ix) { - case IDX_TEMP1_MIN: - flag = data->stat1 & AMC6821_STAT1_LTL; - break; - case IDX_TEMP1_MAX: - flag = data->stat1 & AMC6821_STAT1_LTH; - break; - case IDX_TEMP1_CRIT: - flag = data->stat2 & AMC6821_STAT2_LTC; - break; - case IDX_TEMP2_MIN: - flag = data->stat1 & AMC6821_STAT1_RTL; - break; - case IDX_TEMP2_MAX: - flag = data->stat1 & AMC6821_STAT1_RTH; - break; - case IDX_TEMP2_CRIT: - flag = data->stat2 & AMC6821_STAT2_RTC; - break; - default: - dev_dbg(dev, "Unknown attr->index (%d).\n", ix); - return -EINVAL; - } - if (flag) - return sprintf(buf, "1"); - else - return sprintf(buf, "0"); -} - - - - -static ssize_t get_temp2_fault( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - if (data->stat1 & AMC6821_STAT1_RTF) - return sprintf(buf, "1"); - else - return sprintf(buf, "0"); -} - -static ssize_t get_pwm1( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - return sprintf(buf, "%d\n", data->pwm1); -} - -static ssize_t set_pwm1( - struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - long val; - int ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - data->pwm1 = SENSORS_LIMIT(val , 0, 255); - i2c_smbus_write_byte_data(client, AMC6821_REG_DCY, data->pwm1); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t get_pwm1_enable( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - return sprintf(buf, "%d\n", data->pwm1_enable); -} - -static ssize_t set_pwm1_enable( - struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - long val; - int config = kstrtol(buf, 10, &val); - if (config) - return config; - - config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); - if (config < 0) { - dev_err(&client->dev, - "Error reading configuration register, aborting.\n"); - return -EIO; - } - - switch (val) { - case 1: - config &= ~AMC6821_CONF1_FDRC0; - config &= ~AMC6821_CONF1_FDRC1; - break; - case 2: - config &= ~AMC6821_CONF1_FDRC0; - config |= AMC6821_CONF1_FDRC1; - break; - case 3: - config |= AMC6821_CONF1_FDRC0; - config |= AMC6821_CONF1_FDRC1; - break; - default: - return -EINVAL; - } - mutex_lock(&data->update_lock); - if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { - dev_err(&client->dev, - "Configuration register write error, aborting.\n"); - count = -EIO; - } - mutex_unlock(&data->update_lock); - return count; -} - - -static ssize_t get_pwm1_auto_channels_temp( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp); -} - - -static ssize_t get_temp_auto_point_temp( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - int ix = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - struct amc6821_data *data = amc6821_update_device(dev); - switch (nr) { - case 1: - return sprintf(buf, "%d\n", - data->temp1_auto_point_temp[ix] * 1000); - break; - case 2: - return sprintf(buf, "%d\n", - data->temp2_auto_point_temp[ix] * 1000); - break; - default: - dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); - return -EINVAL; - } -} - - -static ssize_t get_pwm1_auto_point_pwm( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - int ix = to_sensor_dev_attr(devattr)->index; - struct amc6821_data *data = amc6821_update_device(dev); - return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]); -} - - -static inline ssize_t set_slope_register(struct i2c_client *client, - u8 reg, - u8 dpwm, - u8 *ptemp) -{ - int dt; - u8 tmp; - - dt = ptemp[2]-ptemp[1]; - for (tmp = 4; tmp > 0; tmp--) { - if (dt * (0x20 >> tmp) >= dpwm) - break; - } - tmp |= (ptemp[1] & 0x7C) << 1; - if (i2c_smbus_write_byte_data(client, - reg, tmp)) { - dev_err(&client->dev, "Register write error, aborting.\n"); - return -EIO; - } - return 0; -} - - - -static ssize_t set_temp_auto_point_temp( - struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = amc6821_update_device(dev); - int ix = to_sensor_dev_attr_2(attr)->index; - int nr = to_sensor_dev_attr_2(attr)->nr; - u8 *ptemp; - u8 reg; - int dpwm; - long val; - int ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - switch (nr) { - case 1: - ptemp = data->temp1_auto_point_temp; - reg = AMC6821_REG_LTEMP_FAN_CTRL; - break; - case 2: - ptemp = data->temp2_auto_point_temp; - reg = AMC6821_REG_RTEMP_FAN_CTRL; - break; - default: - dev_dbg(dev, "Unknown attr->nr (%d).\n", nr); - return -EINVAL; - } - - data->valid = 0; - mutex_lock(&data->update_lock); - switch (ix) { - case 0: - ptemp[0] = SENSORS_LIMIT(val / 1000, 0, - data->temp1_auto_point_temp[1]); - ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, - data->temp2_auto_point_temp[1]); - ptemp[0] = SENSORS_LIMIT(ptemp[0], 0, 63); - if (i2c_smbus_write_byte_data( - client, - AMC6821_REG_PSV_TEMP, - ptemp[0])) { - dev_err(&client->dev, - "Register write error, aborting.\n"); - count = -EIO; - } - goto EXIT; - break; - case 1: - ptemp[1] = SENSORS_LIMIT( - val / 1000, - (ptemp[0] & 0x7C) + 4, - 124); - ptemp[1] &= 0x7C; - ptemp[2] = SENSORS_LIMIT( - ptemp[2], ptemp[1] + 1, - 255); - break; - case 2: - ptemp[2] = SENSORS_LIMIT( - val / 1000, - ptemp[1]+1, - 255); - break; - default: - dev_dbg(dev, "Unknown attr->index (%d).\n", ix); - count = -EINVAL; - goto EXIT; - } - dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; - if (set_slope_register(client, reg, dpwm, ptemp)) - count = -EIO; - -EXIT: - mutex_unlock(&data->update_lock); - return count; -} - - - -static ssize_t set_pwm1_auto_point_pwm( - struct device *dev, - struct device_attribute *attr, - const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - int dpwm; - long val; - int ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - - mutex_lock(&data->update_lock); - data->pwm1_auto_point_pwm[1] = SENSORS_LIMIT(val, 0, 254); - if (i2c_smbus_write_byte_data(client, AMC6821_REG_DCY_LOW_TEMP, - data->pwm1_auto_point_pwm[1])) { - dev_err(&client->dev, "Register write error, aborting.\n"); - count = -EIO; - goto EXIT; - } - dpwm = data->pwm1_auto_point_pwm[2] - data->pwm1_auto_point_pwm[1]; - if (set_slope_register(client, AMC6821_REG_LTEMP_FAN_CTRL, dpwm, - data->temp1_auto_point_temp)) { - count = -EIO; - goto EXIT; - } - if (set_slope_register(client, AMC6821_REG_RTEMP_FAN_CTRL, dpwm, - data->temp2_auto_point_temp)) { - count = -EIO; - goto EXIT; - } - -EXIT: - data->valid = 0; - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t get_fan( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - int ix = to_sensor_dev_attr(devattr)->index; - if (0 == data->fan[ix]) - return sprintf(buf, "0"); - return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix])); -} - - - -static ssize_t get_fan1_fault( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - if (data->stat1 & AMC6821_STAT1_FANS) - return sprintf(buf, "1"); - else - return sprintf(buf, "0"); -} - - - -static ssize_t set_fan( - struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - long val; - int ix = to_sensor_dev_attr(attr)->index; - int ret = kstrtol(buf, 10, &val); - if (ret) - return ret; - val = 1 > val ? 0xFFFF : 6000000/val; - - mutex_lock(&data->update_lock); - data->fan[ix] = (u16) SENSORS_LIMIT(val, 1, 0xFFFF); - if (i2c_smbus_write_byte_data(client, fan_reg_low[ix], - data->fan[ix] & 0xFF)) { - dev_err(&client->dev, "Register write error, aborting.\n"); - count = -EIO; - goto EXIT; - } - if (i2c_smbus_write_byte_data(client, - fan_reg_hi[ix], data->fan[ix] >> 8)) { - dev_err(&client->dev, "Register write error, aborting.\n"); - count = -EIO; - } -EXIT: - mutex_unlock(&data->update_lock); - return count; -} - - - -static ssize_t get_fan1_div( - struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct amc6821_data *data = amc6821_update_device(dev); - return sprintf(buf, "%d\n", data->fan1_div); -} - -static ssize_t set_fan1_div( - struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - long val; - int config = kstrtol(buf, 10, &val); - if (config) - return config; - - config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); - if (config < 0) { - dev_err(&client->dev, - "Error reading configuration register, aborting.\n"); - return -EIO; - } - mutex_lock(&data->update_lock); - switch (val) { - case 2: - config &= ~AMC6821_CONF4_PSPR; - data->fan1_div = 2; - break; - case 4: - config |= AMC6821_CONF4_PSPR; - data->fan1_div = 4; - break; - default: - count = -EINVAL; - goto EXIT; - } - if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, config)) { - dev_err(&client->dev, - "Configuration register write error, aborting.\n"); - count = -EIO; - } -EXIT: - mutex_unlock(&data->update_lock); - return count; -} - - - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - get_temp, NULL, IDX_TEMP1_INPUT); -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp, - set_temp, IDX_TEMP1_MIN); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, get_temp, - set_temp, IDX_TEMP1_MAX); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, get_temp, - set_temp, IDX_TEMP1_CRIT); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, - get_temp_alarm, NULL, IDX_TEMP1_MIN); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, - get_temp_alarm, NULL, IDX_TEMP1_MAX); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, - get_temp_alarm, NULL, IDX_TEMP1_CRIT); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO | S_IWUSR, - get_temp, NULL, IDX_TEMP2_INPUT); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, get_temp, - set_temp, IDX_TEMP2_MIN); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, get_temp, - set_temp, IDX_TEMP2_MAX); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, get_temp, - set_temp, IDX_TEMP2_CRIT); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, - get_temp2_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, - get_temp_alarm, NULL, IDX_TEMP2_MIN); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, - get_temp_alarm, NULL, IDX_TEMP2_MAX); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, - get_temp_alarm, NULL, IDX_TEMP2_CRIT); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, IDX_FAN1_INPUT); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, - get_fan, set_fan, IDX_FAN1_MIN); -static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO | S_IWUSR, - get_fan, set_fan, IDX_FAN1_MAX); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_fan1_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - get_fan1_div, set_fan1_div, 0); - -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm1, set_pwm1, 0); -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - get_pwm1_enable, set_pwm1_enable, 0); -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IRUGO, - get_pwm1_auto_point_pwm, NULL, 0); -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, - get_pwm1_auto_point_pwm, set_pwm1_auto_point_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IRUGO, - get_pwm1_auto_point_pwm, NULL, 2); -static SENSOR_DEVICE_ATTR(pwm1_auto_channels_temp, S_IRUGO, - get_pwm1_auto_channels_temp, NULL, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_point1_temp, S_IRUGO, - get_temp_auto_point_temp, NULL, 1, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_point2_temp, S_IWUSR | S_IRUGO, - get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 1); -static SENSOR_DEVICE_ATTR_2(temp1_auto_point3_temp, S_IWUSR | S_IRUGO, - get_temp_auto_point_temp, set_temp_auto_point_temp, 1, 2); - -static SENSOR_DEVICE_ATTR_2(temp2_auto_point1_temp, S_IWUSR | S_IRUGO, - get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 0); -static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, - get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO, - get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2); - - - -static struct attribute *amc6821_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_max.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_temp2_auto_point3_temp.dev_attr.attr, - NULL -}; - -static struct attribute_group amc6821_attr_grp = { - .attrs = amc6821_attrs, -}; - - - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int amc6821_detect( - struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - int dev_id, comp_id; - - dev_dbg(&adapter->dev, "amc6821_detect called.\n"); - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - dev_dbg(&adapter->dev, - "amc6821: I2C bus doesn't support byte mode, " - "skipping.\n"); - return -ENODEV; - } - - dev_id = i2c_smbus_read_byte_data(client, AMC6821_REG_DEV_ID); - comp_id = i2c_smbus_read_byte_data(client, AMC6821_REG_COMP_ID); - if (dev_id != 0x21 || comp_id != 0x49) { - dev_dbg(&adapter->dev, - "amc6821: detection failed at 0x%02x.\n", - address); - return -ENODEV; - } - - /* - * Bit 7 of the address register is ignored, so we can check the - * ID registers again - */ - dev_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_DEV_ID); - comp_id = i2c_smbus_read_byte_data(client, 0x80 | AMC6821_REG_COMP_ID); - if (dev_id != 0x21 || comp_id != 0x49) { - dev_dbg(&adapter->dev, - "amc6821: detection failed at 0x%02x.\n", - address); - return -ENODEV; - } - - dev_info(&adapter->dev, "amc6821: chip found at 0x%02x.\n", address); - strlcpy(info->type, "amc6821", I2C_NAME_SIZE); - - return 0; -} - -static int amc6821_probe( - struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct amc6821_data *data; - int err; - - data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "out of memory.\n"); - return -ENOMEM; - } - - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* - * Initialize the amc6821 chip - */ - err = amc6821_init_client(client); - if (err) - goto err_free; - - err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); - if (err) - goto err_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; - - err = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "error registering hwmon device.\n"); - sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); -err_free: - kfree(data); - return err; -} - -static int amc6821_remove(struct i2c_client *client) -{ - struct amc6821_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); - - kfree(data); - - return 0; -} - - -static int amc6821_init_client(struct i2c_client *client) -{ - int config; - int err = -EIO; - - if (init) { - config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); - - if (config < 0) { - dev_err(&client->dev, - "Error reading configuration register, aborting.\n"); - return err; - } - - config |= AMC6821_CONF4_MODE; - - if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF4, - config)) { - dev_err(&client->dev, - "Configuration register write error, aborting.\n"); - return err; - } - - config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF3); - - if (config < 0) { - dev_err(&client->dev, - "Error reading configuration register, aborting.\n"); - return err; - } - - dev_info(&client->dev, "Revision %d\n", config & 0x0f); - - config &= ~AMC6821_CONF3_THERM_FAN_EN; - - if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF3, - config)) { - dev_err(&client->dev, - "Configuration register write error, aborting.\n"); - return err; - } - - config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF2); - - if (config < 0) { - dev_err(&client->dev, - "Error reading configuration register, aborting.\n"); - return err; - } - - config &= ~AMC6821_CONF2_RTFIE; - config &= ~AMC6821_CONF2_LTOIE; - config &= ~AMC6821_CONF2_RTOIE; - if (i2c_smbus_write_byte_data(client, - AMC6821_REG_CONF2, config)) { - dev_err(&client->dev, - "Configuration register write error, aborting.\n"); - return err; - } - - config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); - - if (config < 0) { - dev_err(&client->dev, - "Error reading configuration register, aborting.\n"); - return err; - } - - config &= ~AMC6821_CONF1_THERMOVIE; - config &= ~AMC6821_CONF1_FANIE; - config |= AMC6821_CONF1_START; - if (pwminv) - config |= AMC6821_CONF1_PWMINV; - else - config &= ~AMC6821_CONF1_PWMINV; - - if (i2c_smbus_write_byte_data( - client, AMC6821_REG_CONF1, config)) { - dev_err(&client->dev, - "Configuration register write error, aborting.\n"); - return err; - } - } - return 0; -} - - -static struct amc6821_data *amc6821_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - int timeout = HZ; - u8 reg; - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + timeout) || - !data->valid) { - - for (i = 0; i < TEMP_IDX_LEN; i++) - data->temp[i] = i2c_smbus_read_byte_data(client, - temp_reg[i]); - - data->stat1 = i2c_smbus_read_byte_data(client, - AMC6821_REG_STAT1); - data->stat2 = i2c_smbus_read_byte_data(client, - AMC6821_REG_STAT2); - - data->pwm1 = i2c_smbus_read_byte_data(client, - AMC6821_REG_DCY); - for (i = 0; i < FAN1_IDX_LEN; i++) { - data->fan[i] = i2c_smbus_read_byte_data( - client, - fan_reg_low[i]); - data->fan[i] += i2c_smbus_read_byte_data( - client, - fan_reg_hi[i]) << 8; - } - data->fan1_div = i2c_smbus_read_byte_data(client, - AMC6821_REG_CONF4); - data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; - - data->pwm1_auto_point_pwm[0] = 0; - data->pwm1_auto_point_pwm[2] = 255; - data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, - AMC6821_REG_DCY_LOW_TEMP); - - data->temp1_auto_point_temp[0] = - i2c_smbus_read_byte_data(client, - AMC6821_REG_PSV_TEMP); - data->temp2_auto_point_temp[0] = - data->temp1_auto_point_temp[0]; - reg = i2c_smbus_read_byte_data(client, - AMC6821_REG_LTEMP_FAN_CTRL); - data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; - reg &= 0x07; - reg = 0x20 >> reg; - if (reg > 0) - data->temp1_auto_point_temp[2] = - data->temp1_auto_point_temp[1] + - (data->pwm1_auto_point_pwm[2] - - data->pwm1_auto_point_pwm[1]) / reg; - else - data->temp1_auto_point_temp[2] = 255; - - reg = i2c_smbus_read_byte_data(client, - AMC6821_REG_RTEMP_FAN_CTRL); - data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; - reg &= 0x07; - reg = 0x20 >> reg; - if (reg > 0) - data->temp2_auto_point_temp[2] = - data->temp2_auto_point_temp[1] + - (data->pwm1_auto_point_pwm[2] - - data->pwm1_auto_point_pwm[1]) / reg; - else - data->temp2_auto_point_temp[2] = 255; - - reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); - reg = (reg >> 5) & 0x3; - switch (reg) { - case 0: /*open loop: software sets pwm1*/ - data->pwm1_auto_channels_temp = 0; - data->pwm1_enable = 1; - break; - case 2: /*closed loop: remote T (temp2)*/ - data->pwm1_auto_channels_temp = 2; - data->pwm1_enable = 2; - break; - case 3: /*closed loop: local and remote T (temp2)*/ - data->pwm1_auto_channels_temp = 3; - data->pwm1_enable = 3; - break; - case 1: /* - * semi-open loop: software sets rpm, chip controls - * pwm1, currently not implemented - */ - data->pwm1_auto_channels_temp = 0; - data->pwm1_enable = 0; - break; - } - - data->last_updated = jiffies; - data->valid = 1; - } - mutex_unlock(&data->update_lock); - return data; -} - -module_i2c_driver(amc6821_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("T. Mertelj "); -MODULE_DESCRIPTION("Texas Instruments amc6821 hwmon driver"); diff --git a/ANDROID_3.4.5/drivers/hwmon/applesmc.c b/ANDROID_3.4.5/drivers/hwmon/applesmc.c deleted file mode 100644 index 70d62f5b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/applesmc.c +++ /dev/null @@ -1,1338 +0,0 @@ -/* - * drivers/hwmon/applesmc.c - driver for Apple's SMC (accelerometer, temperature - * sensors, fan control, keyboard backlight control) used in Intel-based Apple - * computers. - * - * Copyright (C) 2007 Nicolas Boichat - * Copyright (C) 2010 Henrik Rydberg - * - * Based on hdaps.c driver: - * Copyright (C) 2005 Robert Love - * Copyright (C) 2005 Jesper Juhl - * - * Fan control based on smcFanControl: - * Copyright (C) 2006 Hendrik Holtmann - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* data port used by Apple SMC */ -#define APPLESMC_DATA_PORT 0x300 -/* command/status port used by Apple SMC */ -#define APPLESMC_CMD_PORT 0x304 - -#define APPLESMC_NR_PORTS 32 /* 0x300-0x31f */ - -#define APPLESMC_MAX_DATA_LENGTH 32 - -/* wait up to 32 ms for a status change. */ -#define APPLESMC_MIN_WAIT 0x0040 -#define APPLESMC_MAX_WAIT 0x8000 - -#define APPLESMC_STATUS_MASK 0x0f -#define APPLESMC_READ_CMD 0x10 -#define APPLESMC_WRITE_CMD 0x11 -#define APPLESMC_GET_KEY_BY_INDEX_CMD 0x12 -#define APPLESMC_GET_KEY_TYPE_CMD 0x13 - -#define KEY_COUNT_KEY "#KEY" /* r-o ui32 */ - -#define LIGHT_SENSOR_LEFT_KEY "ALV0" /* r-o {alv (6-10 bytes) */ -#define LIGHT_SENSOR_RIGHT_KEY "ALV1" /* r-o {alv (6-10 bytes) */ -#define BACKLIGHT_KEY "LKSB" /* w-o {lkb (2 bytes) */ - -#define CLAMSHELL_KEY "MSLD" /* r-o ui8 (unused) */ - -#define MOTION_SENSOR_X_KEY "MO_X" /* r-o sp78 (2 bytes) */ -#define MOTION_SENSOR_Y_KEY "MO_Y" /* r-o sp78 (2 bytes) */ -#define MOTION_SENSOR_Z_KEY "MO_Z" /* r-o sp78 (2 bytes) */ -#define MOTION_SENSOR_KEY "MOCN" /* r/w ui16 */ - -#define FANS_COUNT "FNum" /* r-o ui8 */ -#define FANS_MANUAL "FS! " /* r-w ui16 */ -#define FAN_ID_FMT "F%dID" /* r-o char[16] */ - -/* List of keys used to read/write fan speeds */ -static const char *const fan_speed_fmt[] = { - "F%dAc", /* actual speed */ - "F%dMn", /* minimum speed (rw) */ - "F%dMx", /* maximum speed */ - "F%dSf", /* safe speed - not all models */ - "F%dTg", /* target speed (manual: rw) */ -}; - -#define INIT_TIMEOUT_MSECS 5000 /* wait up to 5s for device init ... */ -#define INIT_WAIT_MSECS 50 /* ... in 50ms increments */ - -#define APPLESMC_POLL_INTERVAL 50 /* msecs */ -#define APPLESMC_INPUT_FUZZ 4 /* input event threshold */ -#define APPLESMC_INPUT_FLAT 4 - -#define SENSOR_X 0 -#define SENSOR_Y 1 -#define SENSOR_Z 2 - -#define to_index(attr) (to_sensor_dev_attr(attr)->index & 0xffff) -#define to_option(attr) (to_sensor_dev_attr(attr)->index >> 16) - -/* Dynamic device node attributes */ -struct applesmc_dev_attr { - struct sensor_device_attribute sda; /* hwmon attributes */ - char name[32]; /* room for node file name */ -}; - -/* Dynamic device node group */ -struct applesmc_node_group { - char *format; /* format string */ - void *show; /* show function */ - void *store; /* store function */ - int option; /* function argument */ - struct applesmc_dev_attr *nodes; /* dynamic node array */ -}; - -/* AppleSMC entry - cached register information */ -struct applesmc_entry { - char key[5]; /* four-letter key code */ - u8 valid; /* set when entry is successfully read once */ - u8 len; /* bounded by APPLESMC_MAX_DATA_LENGTH */ - char type[5]; /* four-letter type code */ - u8 flags; /* 0x10: func; 0x40: write; 0x80: read */ -}; - -/* Register lookup and registers common to all SMCs */ -static struct applesmc_registers { - struct mutex mutex; /* register read/write mutex */ - unsigned int key_count; /* number of SMC registers */ - unsigned int fan_count; /* number of fans */ - unsigned int temp_count; /* number of temperature registers */ - unsigned int temp_begin; /* temperature lower index bound */ - unsigned int temp_end; /* temperature upper index bound */ - int num_light_sensors; /* number of light sensors */ - bool has_accelerometer; /* has motion sensor */ - bool has_key_backlight; /* has keyboard backlight */ - bool init_complete; /* true when fully initialized */ - struct applesmc_entry *cache; /* cached key entries */ -} smcreg = { - .mutex = __MUTEX_INITIALIZER(smcreg.mutex), -}; - -static const int debug; -static struct platform_device *pdev; -static s16 rest_x; -static s16 rest_y; -static u8 backlight_state[2]; - -static struct device *hwmon_dev; -static struct input_polled_dev *applesmc_idev; - -/* - * Last index written to key_at_index sysfs file, and value to use for all other - * key_at_index_* sysfs files. - */ -static unsigned int key_at_index; - -static struct workqueue_struct *applesmc_led_wq; - -/* - * __wait_status - Wait up to 32ms for the status port to get a certain value - * (masked with 0x0f), returning zero if the value is obtained. Callers must - * hold applesmc_lock. - */ -static int __wait_status(u8 val) -{ - int us; - - val = val & APPLESMC_STATUS_MASK; - - for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { - udelay(us); - if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == val) - return 0; - } - - return -EIO; -} - -/* - * special treatment of command port - on newer macbooks, it seems necessary - * to resend the command byte before polling the status again. Callers must - * hold applesmc_lock. - */ -static int send_command(u8 cmd) -{ - int us; - for (us = APPLESMC_MIN_WAIT; us < APPLESMC_MAX_WAIT; us <<= 1) { - outb(cmd, APPLESMC_CMD_PORT); - udelay(us); - if ((inb(APPLESMC_CMD_PORT) & APPLESMC_STATUS_MASK) == 0x0c) - return 0; - } - return -EIO; -} - -static int send_argument(const char *key) -{ - int i; - - for (i = 0; i < 4; i++) { - outb(key[i], APPLESMC_DATA_PORT); - if (__wait_status(0x04)) - return -EIO; - } - return 0; -} - -static int read_smc(u8 cmd, const char *key, u8 *buffer, u8 len) -{ - int i; - - if (send_command(cmd) || send_argument(key)) { - pr_warn("%.4s: read arg fail\n", key); - return -EIO; - } - - outb(len, APPLESMC_DATA_PORT); - - for (i = 0; i < len; i++) { - if (__wait_status(0x05)) { - pr_warn("%.4s: read data fail\n", key); - return -EIO; - } - buffer[i] = inb(APPLESMC_DATA_PORT); - } - - return 0; -} - -static int write_smc(u8 cmd, const char *key, const u8 *buffer, u8 len) -{ - int i; - - if (send_command(cmd) || send_argument(key)) { - pr_warn("%s: write arg fail\n", key); - return -EIO; - } - - outb(len, APPLESMC_DATA_PORT); - - for (i = 0; i < len; i++) { - if (__wait_status(0x04)) { - pr_warn("%s: write data fail\n", key); - return -EIO; - } - outb(buffer[i], APPLESMC_DATA_PORT); - } - - return 0; -} - -static int read_register_count(unsigned int *count) -{ - __be32 be; - int ret; - - ret = read_smc(APPLESMC_READ_CMD, KEY_COUNT_KEY, (u8 *)&be, 4); - if (ret) - return ret; - - *count = be32_to_cpu(be); - return 0; -} - -/* - * Serialized I/O - * - * Returns zero on success or a negative error on failure. - * All functions below are concurrency safe - callers should NOT hold lock. - */ - -static int applesmc_read_entry(const struct applesmc_entry *entry, - u8 *buf, u8 len) -{ - int ret; - - if (entry->len != len) - return -EINVAL; - mutex_lock(&smcreg.mutex); - ret = read_smc(APPLESMC_READ_CMD, entry->key, buf, len); - mutex_unlock(&smcreg.mutex); - - return ret; -} - -static int applesmc_write_entry(const struct applesmc_entry *entry, - const u8 *buf, u8 len) -{ - int ret; - - if (entry->len != len) - return -EINVAL; - mutex_lock(&smcreg.mutex); - ret = write_smc(APPLESMC_WRITE_CMD, entry->key, buf, len); - mutex_unlock(&smcreg.mutex); - return ret; -} - -static const struct applesmc_entry *applesmc_get_entry_by_index(int index) -{ - struct applesmc_entry *cache = &smcreg.cache[index]; - u8 key[4], info[6]; - __be32 be; - int ret = 0; - - if (cache->valid) - return cache; - - mutex_lock(&smcreg.mutex); - - if (cache->valid) - goto out; - be = cpu_to_be32(index); - ret = read_smc(APPLESMC_GET_KEY_BY_INDEX_CMD, (u8 *)&be, key, 4); - if (ret) - goto out; - ret = read_smc(APPLESMC_GET_KEY_TYPE_CMD, key, info, 6); - if (ret) - goto out; - - memcpy(cache->key, key, 4); - cache->len = info[0]; - memcpy(cache->type, &info[1], 4); - cache->flags = info[5]; - cache->valid = 1; - -out: - mutex_unlock(&smcreg.mutex); - if (ret) - return ERR_PTR(ret); - return cache; -} - -static int applesmc_get_lower_bound(unsigned int *lo, const char *key) -{ - int begin = 0, end = smcreg.key_count; - const struct applesmc_entry *entry; - - while (begin != end) { - int middle = begin + (end - begin) / 2; - entry = applesmc_get_entry_by_index(middle); - if (IS_ERR(entry)) { - *lo = 0; - return PTR_ERR(entry); - } - if (strcmp(entry->key, key) < 0) - begin = middle + 1; - else - end = middle; - } - - *lo = begin; - return 0; -} - -static int applesmc_get_upper_bound(unsigned int *hi, const char *key) -{ - int begin = 0, end = smcreg.key_count; - const struct applesmc_entry *entry; - - while (begin != end) { - int middle = begin + (end - begin) / 2; - entry = applesmc_get_entry_by_index(middle); - if (IS_ERR(entry)) { - *hi = smcreg.key_count; - return PTR_ERR(entry); - } - if (strcmp(key, entry->key) < 0) - end = middle; - else - begin = middle + 1; - } - - *hi = begin; - return 0; -} - -static const struct applesmc_entry *applesmc_get_entry_by_key(const char *key) -{ - int begin, end; - int ret; - - ret = applesmc_get_lower_bound(&begin, key); - if (ret) - return ERR_PTR(ret); - ret = applesmc_get_upper_bound(&end, key); - if (ret) - return ERR_PTR(ret); - if (end - begin != 1) - return ERR_PTR(-EINVAL); - - return applesmc_get_entry_by_index(begin); -} - -static int applesmc_read_key(const char *key, u8 *buffer, u8 len) -{ - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_key(key); - if (IS_ERR(entry)) - return PTR_ERR(entry); - - return applesmc_read_entry(entry, buffer, len); -} - -static int applesmc_write_key(const char *key, const u8 *buffer, u8 len) -{ - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_key(key); - if (IS_ERR(entry)) - return PTR_ERR(entry); - - return applesmc_write_entry(entry, buffer, len); -} - -static int applesmc_has_key(const char *key, bool *value) -{ - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_key(key); - if (IS_ERR(entry) && PTR_ERR(entry) != -EINVAL) - return PTR_ERR(entry); - - *value = !IS_ERR(entry); - return 0; -} - -/* - * applesmc_read_motion_sensor - Read motion sensor (X, Y or Z). - */ -static int applesmc_read_motion_sensor(int index, s16 *value) -{ - u8 buffer[2]; - int ret; - - switch (index) { - case SENSOR_X: - ret = applesmc_read_key(MOTION_SENSOR_X_KEY, buffer, 2); - break; - case SENSOR_Y: - ret = applesmc_read_key(MOTION_SENSOR_Y_KEY, buffer, 2); - break; - case SENSOR_Z: - ret = applesmc_read_key(MOTION_SENSOR_Z_KEY, buffer, 2); - break; - default: - ret = -EINVAL; - } - - *value = ((s16)buffer[0] << 8) | buffer[1]; - - return ret; -} - -/* - * applesmc_device_init - initialize the accelerometer. Can sleep. - */ -static void applesmc_device_init(void) -{ - int total; - u8 buffer[2]; - - if (!smcreg.has_accelerometer) - return; - - for (total = INIT_TIMEOUT_MSECS; total > 0; total -= INIT_WAIT_MSECS) { - if (!applesmc_read_key(MOTION_SENSOR_KEY, buffer, 2) && - (buffer[0] != 0x00 || buffer[1] != 0x00)) - return; - buffer[0] = 0xe0; - buffer[1] = 0x00; - applesmc_write_key(MOTION_SENSOR_KEY, buffer, 2); - msleep(INIT_WAIT_MSECS); - } - - pr_warn("failed to init the device\n"); -} - -/* - * applesmc_init_smcreg_try - Try to initialize register cache. Idempotent. - */ -static int applesmc_init_smcreg_try(void) -{ - struct applesmc_registers *s = &smcreg; - bool left_light_sensor, right_light_sensor; - u8 tmp[1]; - int ret; - - if (s->init_complete) - return 0; - - ret = read_register_count(&s->key_count); - if (ret) - return ret; - - if (!s->cache) - s->cache = kcalloc(s->key_count, sizeof(*s->cache), GFP_KERNEL); - if (!s->cache) - return -ENOMEM; - - ret = applesmc_read_key(FANS_COUNT, tmp, 1); - if (ret) - return ret; - s->fan_count = tmp[0]; - - ret = applesmc_get_lower_bound(&s->temp_begin, "T"); - if (ret) - return ret; - ret = applesmc_get_lower_bound(&s->temp_end, "U"); - if (ret) - return ret; - s->temp_count = s->temp_end - s->temp_begin; - - ret = applesmc_has_key(LIGHT_SENSOR_LEFT_KEY, &left_light_sensor); - if (ret) - return ret; - ret = applesmc_has_key(LIGHT_SENSOR_RIGHT_KEY, &right_light_sensor); - if (ret) - return ret; - ret = applesmc_has_key(MOTION_SENSOR_KEY, &s->has_accelerometer); - if (ret) - return ret; - ret = applesmc_has_key(BACKLIGHT_KEY, &s->has_key_backlight); - if (ret) - return ret; - - s->num_light_sensors = left_light_sensor + right_light_sensor; - s->init_complete = true; - - pr_info("key=%d fan=%d temp=%d acc=%d lux=%d kbd=%d\n", - s->key_count, s->fan_count, s->temp_count, - s->has_accelerometer, - s->num_light_sensors, - s->has_key_backlight); - - return 0; -} - -/* - * applesmc_init_smcreg - Initialize register cache. - * - * Retries until initialization is successful, or the operation times out. - * - */ -static int applesmc_init_smcreg(void) -{ - int ms, ret; - - for (ms = 0; ms < INIT_TIMEOUT_MSECS; ms += INIT_WAIT_MSECS) { - ret = applesmc_init_smcreg_try(); - if (!ret) { - if (ms) - pr_info("init_smcreg() took %d ms\n", ms); - return 0; - } - msleep(INIT_WAIT_MSECS); - } - - kfree(smcreg.cache); - smcreg.cache = NULL; - - return ret; -} - -static void applesmc_destroy_smcreg(void) -{ - kfree(smcreg.cache); - smcreg.cache = NULL; - smcreg.init_complete = false; -} - -/* Device model stuff */ -static int applesmc_probe(struct platform_device *dev) -{ - int ret; - - ret = applesmc_init_smcreg(); - if (ret) - return ret; - - applesmc_device_init(); - - return 0; -} - -/* Synchronize device with memorized backlight state */ -static int applesmc_pm_resume(struct device *dev) -{ - if (smcreg.has_key_backlight) - applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); - return 0; -} - -/* Reinitialize device on resume from hibernation */ -static int applesmc_pm_restore(struct device *dev) -{ - applesmc_device_init(); - return applesmc_pm_resume(dev); -} - -static const struct dev_pm_ops applesmc_pm_ops = { - .resume = applesmc_pm_resume, - .restore = applesmc_pm_restore, -}; - -static struct platform_driver applesmc_driver = { - .probe = applesmc_probe, - .driver = { - .name = "applesmc", - .owner = THIS_MODULE, - .pm = &applesmc_pm_ops, - }, -}; - -/* - * applesmc_calibrate - Set our "resting" values. Callers must - * hold applesmc_lock. - */ -static void applesmc_calibrate(void) -{ - applesmc_read_motion_sensor(SENSOR_X, &rest_x); - applesmc_read_motion_sensor(SENSOR_Y, &rest_y); - rest_x = -rest_x; -} - -static void applesmc_idev_poll(struct input_polled_dev *dev) -{ - struct input_dev *idev = dev->input; - s16 x, y; - - if (applesmc_read_motion_sensor(SENSOR_X, &x)) - return; - if (applesmc_read_motion_sensor(SENSOR_Y, &y)) - return; - - x = -x; - input_report_abs(idev, ABS_X, x - rest_x); - input_report_abs(idev, ABS_Y, y - rest_y); - input_sync(idev); -} - -/* Sysfs Files */ - -static ssize_t applesmc_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return snprintf(buf, PAGE_SIZE, "applesmc\n"); -} - -static ssize_t applesmc_position_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int ret; - s16 x, y, z; - - ret = applesmc_read_motion_sensor(SENSOR_X, &x); - if (ret) - goto out; - ret = applesmc_read_motion_sensor(SENSOR_Y, &y); - if (ret) - goto out; - ret = applesmc_read_motion_sensor(SENSOR_Z, &z); - if (ret) - goto out; - -out: - if (ret) - return ret; - else - return snprintf(buf, PAGE_SIZE, "(%d,%d,%d)\n", x, y, z); -} - -static ssize_t applesmc_light_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - const struct applesmc_entry *entry; - static int data_length; - int ret; - u8 left = 0, right = 0; - u8 buffer[10]; - - if (!data_length) { - entry = applesmc_get_entry_by_key(LIGHT_SENSOR_LEFT_KEY); - if (IS_ERR(entry)) - return PTR_ERR(entry); - if (entry->len > 10) - return -ENXIO; - data_length = entry->len; - pr_info("light sensor data length set to %d\n", data_length); - } - - ret = applesmc_read_key(LIGHT_SENSOR_LEFT_KEY, buffer, data_length); - /* newer macbooks report a single 10-bit bigendian value */ - if (data_length == 10) { - left = be16_to_cpu(*(__be16 *)(buffer + 6)) >> 2; - goto out; - } - left = buffer[2]; - if (ret) - goto out; - ret = applesmc_read_key(LIGHT_SENSOR_RIGHT_KEY, buffer, data_length); - right = buffer[2]; - -out: - if (ret) - return ret; - else - return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", left, right); -} - -/* Displays sensor key as label */ -static ssize_t applesmc_show_sensor_label(struct device *dev, - struct device_attribute *devattr, char *sysfsbuf) -{ - int index = smcreg.temp_begin + to_index(devattr); - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_index(index); - if (IS_ERR(entry)) - return PTR_ERR(entry); - - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); -} - -/* Displays degree Celsius * 1000 */ -static ssize_t applesmc_show_temperature(struct device *dev, - struct device_attribute *devattr, char *sysfsbuf) -{ - int index = smcreg.temp_begin + to_index(devattr); - const struct applesmc_entry *entry; - int ret; - u8 buffer[2]; - unsigned int temp; - - entry = applesmc_get_entry_by_index(index); - if (IS_ERR(entry)) - return PTR_ERR(entry); - if (entry->len > 2) - return -EINVAL; - - ret = applesmc_read_entry(entry, buffer, entry->len); - if (ret) - return ret; - - if (entry->len == 2) { - temp = buffer[0] * 1000; - temp += (buffer[1] >> 6) * 250; - } else { - temp = buffer[0] * 4000; - } - - return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", temp); -} - -static ssize_t applesmc_show_fan_speed(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - int ret; - unsigned int speed = 0; - char newkey[5]; - u8 buffer[2]; - - sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr)); - - ret = applesmc_read_key(newkey, buffer, 2); - speed = ((buffer[0] << 8 | buffer[1]) >> 2); - - if (ret) - return ret; - else - return snprintf(sysfsbuf, PAGE_SIZE, "%u\n", speed); -} - -static ssize_t applesmc_store_fan_speed(struct device *dev, - struct device_attribute *attr, - const char *sysfsbuf, size_t count) -{ - int ret; - unsigned long speed; - char newkey[5]; - u8 buffer[2]; - - if (kstrtoul(sysfsbuf, 10, &speed) < 0 || speed >= 0x4000) - return -EINVAL; /* Bigger than a 14-bit value */ - - sprintf(newkey, fan_speed_fmt[to_option(attr)], to_index(attr)); - - buffer[0] = (speed >> 6) & 0xff; - buffer[1] = (speed << 2) & 0xff; - ret = applesmc_write_key(newkey, buffer, 2); - - if (ret) - return ret; - else - return count; -} - -static ssize_t applesmc_show_fan_manual(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - int ret; - u16 manual = 0; - u8 buffer[2]; - - ret = applesmc_read_key(FANS_MANUAL, buffer, 2); - manual = ((buffer[0] << 8 | buffer[1]) >> to_index(attr)) & 0x01; - - if (ret) - return ret; - else - return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", manual); -} - -static ssize_t applesmc_store_fan_manual(struct device *dev, - struct device_attribute *attr, - const char *sysfsbuf, size_t count) -{ - int ret; - u8 buffer[2]; - unsigned long input; - u16 val; - - if (kstrtoul(sysfsbuf, 10, &input) < 0) - return -EINVAL; - - ret = applesmc_read_key(FANS_MANUAL, buffer, 2); - val = (buffer[0] << 8 | buffer[1]); - if (ret) - goto out; - - if (input) - val = val | (0x01 << to_index(attr)); - else - val = val & ~(0x01 << to_index(attr)); - - buffer[0] = (val >> 8) & 0xFF; - buffer[1] = val & 0xFF; - - ret = applesmc_write_key(FANS_MANUAL, buffer, 2); - -out: - if (ret) - return ret; - else - return count; -} - -static ssize_t applesmc_show_fan_position(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - int ret; - char newkey[5]; - u8 buffer[17]; - - sprintf(newkey, FAN_ID_FMT, to_index(attr)); - - ret = applesmc_read_key(newkey, buffer, 16); - buffer[16] = 0; - - if (ret) - return ret; - else - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", buffer+4); -} - -static ssize_t applesmc_calibrate_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - return snprintf(sysfsbuf, PAGE_SIZE, "(%d,%d)\n", rest_x, rest_y); -} - -static ssize_t applesmc_calibrate_store(struct device *dev, - struct device_attribute *attr, const char *sysfsbuf, size_t count) -{ - applesmc_calibrate(); - - return count; -} - -static void applesmc_backlight_set(struct work_struct *work) -{ - applesmc_write_key(BACKLIGHT_KEY, backlight_state, 2); -} -static DECLARE_WORK(backlight_work, &applesmc_backlight_set); - -static void applesmc_brightness_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - int ret; - - backlight_state[0] = value; - ret = queue_work(applesmc_led_wq, &backlight_work); - - if (debug && (!ret)) - printk(KERN_DEBUG "applesmc: work was already on the queue.\n"); -} - -static ssize_t applesmc_key_count_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - int ret; - u8 buffer[4]; - u32 count; - - ret = applesmc_read_key(KEY_COUNT_KEY, buffer, 4); - count = ((u32)buffer[0]<<24) + ((u32)buffer[1]<<16) + - ((u32)buffer[2]<<8) + buffer[3]; - - if (ret) - return ret; - else - return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", count); -} - -static ssize_t applesmc_key_at_index_read_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - const struct applesmc_entry *entry; - int ret; - - entry = applesmc_get_entry_by_index(key_at_index); - if (IS_ERR(entry)) - return PTR_ERR(entry); - ret = applesmc_read_entry(entry, sysfsbuf, entry->len); - if (ret) - return ret; - - return entry->len; -} - -static ssize_t applesmc_key_at_index_data_length_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_index(key_at_index); - if (IS_ERR(entry)) - return PTR_ERR(entry); - - return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", entry->len); -} - -static ssize_t applesmc_key_at_index_type_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_index(key_at_index); - if (IS_ERR(entry)) - return PTR_ERR(entry); - - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->type); -} - -static ssize_t applesmc_key_at_index_name_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - const struct applesmc_entry *entry; - - entry = applesmc_get_entry_by_index(key_at_index); - if (IS_ERR(entry)) - return PTR_ERR(entry); - - return snprintf(sysfsbuf, PAGE_SIZE, "%s\n", entry->key); -} - -static ssize_t applesmc_key_at_index_show(struct device *dev, - struct device_attribute *attr, char *sysfsbuf) -{ - return snprintf(sysfsbuf, PAGE_SIZE, "%d\n", key_at_index); -} - -static ssize_t applesmc_key_at_index_store(struct device *dev, - struct device_attribute *attr, const char *sysfsbuf, size_t count) -{ - unsigned long newkey; - - if (kstrtoul(sysfsbuf, 10, &newkey) < 0 - || newkey >= smcreg.key_count) - return -EINVAL; - - key_at_index = newkey; - return count; -} - -static struct led_classdev applesmc_backlight = { - .name = "smc::kbd_backlight", - .default_trigger = "nand-disk", - .brightness_set = applesmc_brightness_set, -}; - -static struct applesmc_node_group info_group[] = { - { "name", applesmc_name_show }, - { "key_count", applesmc_key_count_show }, - { "key_at_index", applesmc_key_at_index_show, applesmc_key_at_index_store }, - { "key_at_index_name", applesmc_key_at_index_name_show }, - { "key_at_index_type", applesmc_key_at_index_type_show }, - { "key_at_index_data_length", applesmc_key_at_index_data_length_show }, - { "key_at_index_data", applesmc_key_at_index_read_show }, - { } -}; - -static struct applesmc_node_group accelerometer_group[] = { - { "position", applesmc_position_show }, - { "calibrate", applesmc_calibrate_show, applesmc_calibrate_store }, - { } -}; - -static struct applesmc_node_group light_sensor_group[] = { - { "light", applesmc_light_show }, - { } -}; - -static struct applesmc_node_group fan_group[] = { - { "fan%d_label", applesmc_show_fan_position }, - { "fan%d_input", applesmc_show_fan_speed, NULL, 0 }, - { "fan%d_min", applesmc_show_fan_speed, applesmc_store_fan_speed, 1 }, - { "fan%d_max", applesmc_show_fan_speed, NULL, 2 }, - { "fan%d_safe", applesmc_show_fan_speed, NULL, 3 }, - { "fan%d_output", applesmc_show_fan_speed, applesmc_store_fan_speed, 4 }, - { "fan%d_manual", applesmc_show_fan_manual, applesmc_store_fan_manual }, - { } -}; - -static struct applesmc_node_group temp_group[] = { - { "temp%d_label", applesmc_show_sensor_label }, - { "temp%d_input", applesmc_show_temperature }, - { } -}; - -/* Module stuff */ - -/* - * applesmc_destroy_nodes - remove files and free associated memory - */ -static void applesmc_destroy_nodes(struct applesmc_node_group *groups) -{ - struct applesmc_node_group *grp; - struct applesmc_dev_attr *node; - - for (grp = groups; grp->nodes; grp++) { - for (node = grp->nodes; node->sda.dev_attr.attr.name; node++) - sysfs_remove_file(&pdev->dev.kobj, - &node->sda.dev_attr.attr); - kfree(grp->nodes); - grp->nodes = NULL; - } -} - -/* - * applesmc_create_nodes - create a two-dimensional group of sysfs files - */ -static int applesmc_create_nodes(struct applesmc_node_group *groups, int num) -{ - struct applesmc_node_group *grp; - struct applesmc_dev_attr *node; - struct attribute *attr; - int ret, i; - - for (grp = groups; grp->format; grp++) { - grp->nodes = kcalloc(num + 1, sizeof(*node), GFP_KERNEL); - if (!grp->nodes) { - ret = -ENOMEM; - goto out; - } - for (i = 0; i < num; i++) { - node = &grp->nodes[i]; - sprintf(node->name, grp->format, i + 1); - node->sda.index = (grp->option << 16) | (i & 0xffff); - node->sda.dev_attr.show = grp->show; - node->sda.dev_attr.store = grp->store; - attr = &node->sda.dev_attr.attr; - sysfs_attr_init(attr); - attr->name = node->name; - attr->mode = S_IRUGO | (grp->store ? S_IWUSR : 0); - ret = sysfs_create_file(&pdev->dev.kobj, attr); - if (ret) { - attr->name = NULL; - goto out; - } - } - } - - return 0; -out: - applesmc_destroy_nodes(groups); - return ret; -} - -/* Create accelerometer ressources */ -static int applesmc_create_accelerometer(void) -{ - struct input_dev *idev; - int ret; - - if (!smcreg.has_accelerometer) - return 0; - - ret = applesmc_create_nodes(accelerometer_group, 1); - if (ret) - goto out; - - applesmc_idev = input_allocate_polled_device(); - if (!applesmc_idev) { - ret = -ENOMEM; - goto out_sysfs; - } - - applesmc_idev->poll = applesmc_idev_poll; - applesmc_idev->poll_interval = APPLESMC_POLL_INTERVAL; - - /* initial calibrate for the input device */ - applesmc_calibrate(); - - /* initialize the input device */ - idev = applesmc_idev->input; - idev->name = "applesmc"; - idev->id.bustype = BUS_HOST; - idev->dev.parent = &pdev->dev; - idev->evbit[0] = BIT_MASK(EV_ABS); - input_set_abs_params(idev, ABS_X, - -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); - input_set_abs_params(idev, ABS_Y, - -256, 256, APPLESMC_INPUT_FUZZ, APPLESMC_INPUT_FLAT); - - ret = input_register_polled_device(applesmc_idev); - if (ret) - goto out_idev; - - return 0; - -out_idev: - input_free_polled_device(applesmc_idev); - -out_sysfs: - applesmc_destroy_nodes(accelerometer_group); - -out: - pr_warn("driver init failed (ret=%d)!\n", ret); - return ret; -} - -/* Release all ressources used by the accelerometer */ -static void applesmc_release_accelerometer(void) -{ - if (!smcreg.has_accelerometer) - return; - input_unregister_polled_device(applesmc_idev); - input_free_polled_device(applesmc_idev); - applesmc_destroy_nodes(accelerometer_group); -} - -static int applesmc_create_light_sensor(void) -{ - if (!smcreg.num_light_sensors) - return 0; - return applesmc_create_nodes(light_sensor_group, 1); -} - -static void applesmc_release_light_sensor(void) -{ - if (!smcreg.num_light_sensors) - return; - applesmc_destroy_nodes(light_sensor_group); -} - -static int applesmc_create_key_backlight(void) -{ - if (!smcreg.has_key_backlight) - return 0; - applesmc_led_wq = create_singlethread_workqueue("applesmc-led"); - if (!applesmc_led_wq) - return -ENOMEM; - return led_classdev_register(&pdev->dev, &applesmc_backlight); -} - -static void applesmc_release_key_backlight(void) -{ - if (!smcreg.has_key_backlight) - return; - led_classdev_unregister(&applesmc_backlight); - destroy_workqueue(applesmc_led_wq); -} - -static int applesmc_dmi_match(const struct dmi_system_id *id) -{ - return 1; -} - -/* - * Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1". - * So we need to put "Apple MacBook Pro" before "Apple MacBook". - */ -static __initdata struct dmi_system_id applesmc_whitelist[] = { - { applesmc_dmi_match, "Apple MacBook Air", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookAir") }, - }, - { applesmc_dmi_match, "Apple MacBook Pro", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro") }, - }, - { applesmc_dmi_match, "Apple MacBook", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacBook") }, - }, - { applesmc_dmi_match, "Apple Macmini", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "Macmini") }, - }, - { applesmc_dmi_match, "Apple MacPro", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "MacPro") }, - }, - { applesmc_dmi_match, "Apple iMac", { - DMI_MATCH(DMI_BOARD_VENDOR, "Apple"), - DMI_MATCH(DMI_PRODUCT_NAME, "iMac") }, - }, - { .ident = NULL } -}; - -static int __init applesmc_init(void) -{ - int ret; - - if (!dmi_check_system(applesmc_whitelist)) { - pr_warn("supported laptop not found!\n"); - ret = -ENODEV; - goto out; - } - - if (!request_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS, - "applesmc")) { - ret = -ENXIO; - goto out; - } - - ret = platform_driver_register(&applesmc_driver); - if (ret) - goto out_region; - - pdev = platform_device_register_simple("applesmc", APPLESMC_DATA_PORT, - NULL, 0); - if (IS_ERR(pdev)) { - ret = PTR_ERR(pdev); - goto out_driver; - } - - /* create register cache */ - ret = applesmc_init_smcreg(); - if (ret) - goto out_device; - - ret = applesmc_create_nodes(info_group, 1); - if (ret) - goto out_smcreg; - - ret = applesmc_create_nodes(fan_group, smcreg.fan_count); - if (ret) - goto out_info; - - ret = applesmc_create_nodes(temp_group, smcreg.temp_count); - if (ret) - goto out_fans; - - ret = applesmc_create_accelerometer(); - if (ret) - goto out_temperature; - - ret = applesmc_create_light_sensor(); - if (ret) - goto out_accelerometer; - - ret = applesmc_create_key_backlight(); - if (ret) - goto out_light_sysfs; - - hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon_dev)) { - ret = PTR_ERR(hwmon_dev); - goto out_light_ledclass; - } - - return 0; - -out_light_ledclass: - applesmc_release_key_backlight(); -out_light_sysfs: - applesmc_release_light_sensor(); -out_accelerometer: - applesmc_release_accelerometer(); -out_temperature: - applesmc_destroy_nodes(temp_group); -out_fans: - applesmc_destroy_nodes(fan_group); -out_info: - applesmc_destroy_nodes(info_group); -out_smcreg: - applesmc_destroy_smcreg(); -out_device: - platform_device_unregister(pdev); -out_driver: - platform_driver_unregister(&applesmc_driver); -out_region: - release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); -out: - pr_warn("driver init failed (ret=%d)!\n", ret); - return ret; -} - -static void __exit applesmc_exit(void) -{ - hwmon_device_unregister(hwmon_dev); - applesmc_release_key_backlight(); - applesmc_release_light_sensor(); - applesmc_release_accelerometer(); - applesmc_destroy_nodes(temp_group); - applesmc_destroy_nodes(fan_group); - applesmc_destroy_nodes(info_group); - applesmc_destroy_smcreg(); - platform_device_unregister(pdev); - platform_driver_unregister(&applesmc_driver); - release_region(APPLESMC_DATA_PORT, APPLESMC_NR_PORTS); -} - -module_init(applesmc_init); -module_exit(applesmc_exit); - -MODULE_AUTHOR("Nicolas Boichat"); -MODULE_DESCRIPTION("Apple SMC"); -MODULE_LICENSE("GPL v2"); -MODULE_DEVICE_TABLE(dmi, applesmc_whitelist); diff --git a/ANDROID_3.4.5/drivers/hwmon/asb100.c b/ANDROID_3.4.5/drivers/hwmon/asb100.c deleted file mode 100644 index 4b8814de..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/asb100.c +++ /dev/null @@ -1,1025 +0,0 @@ -/* - * asb100.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * - * Copyright (C) 2004 Mark M. Hoffman - * - * (derived from w83781d.c) - * - * Copyright (C) 1998 - 2003 Frodo Looijaard , - * Philip Edelbrock , and - * 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. - */ - -/* - * This driver supports the hardware sensor chips: Asus ASB100 and - * ASB100-A "BACH". - * - * ASB100-A supports pwm1, while plain ASB100 does not. There is no known - * way for the driver to tell which one is there. - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * asb100 7 3 1 4 0x31 0x0694 yes no - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lm75.h" - -/* I2C addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2d, I2C_CLIENT_END }; - -static unsigned short force_subclients[4]; -module_param_array(force_subclients, short, NULL, 0); -MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); - -/* Voltage IN registers 0-6 */ -#define ASB100_REG_IN(nr) (0x20 + (nr)) -#define ASB100_REG_IN_MAX(nr) (0x2b + (nr * 2)) -#define ASB100_REG_IN_MIN(nr) (0x2c + (nr * 2)) - -/* FAN IN registers 1-3 */ -#define ASB100_REG_FAN(nr) (0x28 + (nr)) -#define ASB100_REG_FAN_MIN(nr) (0x3b + (nr)) - -/* TEMPERATURE registers 1-4 */ -static const u16 asb100_reg_temp[] = {0, 0x27, 0x150, 0x250, 0x17}; -static const u16 asb100_reg_temp_max[] = {0, 0x39, 0x155, 0x255, 0x18}; -static const u16 asb100_reg_temp_hyst[] = {0, 0x3a, 0x153, 0x253, 0x19}; - -#define ASB100_REG_TEMP(nr) (asb100_reg_temp[nr]) -#define ASB100_REG_TEMP_MAX(nr) (asb100_reg_temp_max[nr]) -#define ASB100_REG_TEMP_HYST(nr) (asb100_reg_temp_hyst[nr]) - -#define ASB100_REG_TEMP2_CONFIG 0x0152 -#define ASB100_REG_TEMP3_CONFIG 0x0252 - - -#define ASB100_REG_CONFIG 0x40 -#define ASB100_REG_ALARM1 0x41 -#define ASB100_REG_ALARM2 0x42 -#define ASB100_REG_SMIM1 0x43 -#define ASB100_REG_SMIM2 0x44 -#define ASB100_REG_VID_FANDIV 0x47 -#define ASB100_REG_I2C_ADDR 0x48 -#define ASB100_REG_CHIPID 0x49 -#define ASB100_REG_I2C_SUBADDR 0x4a -#define ASB100_REG_PIN 0x4b -#define ASB100_REG_IRQ 0x4c -#define ASB100_REG_BANK 0x4e -#define ASB100_REG_CHIPMAN 0x4f - -#define ASB100_REG_WCHIPID 0x58 - -/* bit 7 -> enable, bits 0-3 -> duty cycle */ -#define ASB100_REG_PWM1 0x59 - -/* - * CONVERSIONS - * Rounding and limit checking is only done on the TO_REG variants. - */ - -/* These constants are a guess, consistent w/ w83781d */ -#define ASB100_IN_MIN 0 -#define ASB100_IN_MAX 4080 - -/* - * IN: 1/1000 V (0V to 4.08V) - * REG: 16mV/bit - */ -static u8 IN_TO_REG(unsigned val) -{ - unsigned nval = SENSORS_LIMIT(val, ASB100_IN_MIN, ASB100_IN_MAX); - return (nval + 8) / 16; -} - -static unsigned IN_FROM_REG(u8 reg) -{ - return reg * 16; -} - -static u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm == -1) - return 0; - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -static int FAN_FROM_REG(u8 val, int div) -{ - return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div); -} - -/* These constants are a guess, consistent w/ w83781d */ -#define ASB100_TEMP_MIN -128000 -#define ASB100_TEMP_MAX 127000 - -/* - * TEMP: 0.001C/bit (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static u8 TEMP_TO_REG(long temp) -{ - int ntemp = SENSORS_LIMIT(temp, ASB100_TEMP_MIN, ASB100_TEMP_MAX); - ntemp += (ntemp < 0 ? -500 : 500); - return (u8)(ntemp / 1000); -} - -static int TEMP_FROM_REG(u8 reg) -{ - return (s8)reg * 1000; -} - -/* - * PWM: 0 - 255 per sensors documentation - * REG: (6.25% duty cycle per bit) - */ -static u8 ASB100_PWM_TO_REG(int pwm) -{ - pwm = SENSORS_LIMIT(pwm, 0, 255); - return (u8)(pwm / 16); -} - -static int ASB100_PWM_FROM_REG(u8 reg) -{ - return reg * 16; -} - -#define DIV_FROM_REG(val) (1 << (val)) - -/* - * FAN DIV: 1, 2, 4, or 8 (defaults to 2) - * REG: 0, 1, 2, or 3 (respectively) (defaults to 1) - */ -static u8 DIV_TO_REG(long val) -{ - return val == 8 ? 3 : val == 4 ? 2 : val == 1 ? 0 : 1; -} - -/* - * For each registered client, we need to keep some data in memory. That - * data is pointed to by client->data. The structure itself is - * dynamically allocated, at the same time the client itself is allocated. - */ -struct asb100_data { - struct device *hwmon_dev; - struct mutex lock; - - struct mutex update_lock; - unsigned long last_updated; /* In jiffies */ - - /* array of 2 pointers to subclients */ - struct i2c_client *lm75[2]; - - char valid; /* !=0 if following fields are valid */ - u8 in[7]; /* Register value */ - u8 in_max[7]; /* Register value */ - u8 in_min[7]; /* Register value */ - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - u16 temp[4]; /* Register value (0 and 3 are u8 only) */ - u16 temp_max[4]; /* Register value (0 and 3 are u8 only) */ - u16 temp_hyst[4]; /* Register value (0 and 3 are u8 only) */ - u8 fan_div[3]; /* Register encoding, right justified */ - u8 pwm; /* Register encoding */ - u8 vid; /* Register encoding, combined */ - u32 alarms; /* Register encoding, combined */ - u8 vrm; -}; - -static int asb100_read_value(struct i2c_client *client, u16 reg); -static void asb100_write_value(struct i2c_client *client, u16 reg, u16 val); - -static int asb100_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int asb100_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int asb100_remove(struct i2c_client *client); -static struct asb100_data *asb100_update_device(struct device *dev); -static void asb100_init_client(struct i2c_client *client); - -static const struct i2c_device_id asb100_id[] = { - { "asb100", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, asb100_id); - -static struct i2c_driver asb100_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "asb100", - }, - .probe = asb100_probe, - .remove = asb100_remove, - .id_table = asb100_id, - .detect = asb100_detect, - .address_list = normal_i2c, -}; - -/* 7 Voltages */ -#define show_in_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct asb100_data *data = asb100_update_device(dev); \ - return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \ -} - -show_in_reg(in) -show_in_reg(in_min) -show_in_reg(in_max) - -#define set_in_reg(REG, reg) \ -static ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct i2c_client *client = to_i2c_client(dev); \ - struct asb100_data *data = i2c_get_clientdata(client); \ - unsigned long val; \ - int err = kstrtoul(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - asb100_write_value(client, ASB100_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -set_in_reg(MIN, min) -set_in_reg(MAX, max) - -#define sysfs_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset) - -sysfs_in(0); -sysfs_in(1); -sysfs_in(2); -sysfs_in(3); -sysfs_in(4); -sysfs_in(5); -sysfs_in(6); - -/* 3 Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long min; - int reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - data->fan_div[nr] = DIV_TO_REG(val); - - switch (nr) { - case 0: /* fan 1 */ - reg = asb100_read_value(client, ASB100_REG_VID_FANDIV); - reg = (reg & 0xcf) | (data->fan_div[0] << 4); - asb100_write_value(client, ASB100_REG_VID_FANDIV, reg); - break; - - case 1: /* fan 2 */ - reg = asb100_read_value(client, ASB100_REG_VID_FANDIV); - reg = (reg & 0x3f) | (data->fan_div[1] << 6); - asb100_write_value(client, ASB100_REG_VID_FANDIV, reg); - break; - - case 2: /* fan 3 */ - reg = asb100_read_value(client, ASB100_REG_PIN); - reg = (reg & 0x3f) | (data->fan_div[2] << 6); - asb100_write_value(client, ASB100_REG_PIN, reg); - break; - } - - data->fan_min[nr] = - FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - asb100_write_value(client, ASB100_REG_FAN_MIN(nr), data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - - return count; -} - -#define sysfs_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1) - -sysfs_fan(1); -sysfs_fan(2); -sysfs_fan(3); - -/* 4 Temp. Sensors */ -static int sprintf_temp_from_reg(u16 reg, char *buf, int nr) -{ - int ret = 0; - - switch (nr) { - case 1: case 2: - ret = sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(reg)); - break; - case 0: case 3: default: - ret = sprintf(buf, "%d\n", TEMP_FROM_REG(reg)); - break; - } - return ret; -} - -#define show_temp_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct asb100_data *data = asb100_update_device(dev); \ - return sprintf_temp_from_reg(data->reg[nr], buf, nr); \ -} - -show_temp_reg(temp); -show_temp_reg(temp_max); -show_temp_reg(temp_hyst); - -#define set_temp_reg(REG, reg) \ -static ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct i2c_client *client = to_i2c_client(dev); \ - struct asb100_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - switch (nr) { \ - case 1: case 2: \ - data->reg[nr] = LM75_TEMP_TO_REG(val); \ - break; \ - case 0: case 3: default: \ - data->reg[nr] = TEMP_TO_REG(val); \ - break; \ - } \ - asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \ - data->reg[nr]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -set_temp_reg(MAX, temp_max); -set_temp_reg(HYST, temp_hyst); - -#define sysfs_temp(num) \ -static SENSOR_DEVICE_ATTR(temp##num##_input, S_IRUGO, \ - show_temp, NULL, num - 1); \ -static SENSOR_DEVICE_ATTR(temp##num##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, num - 1); \ -static SENSOR_DEVICE_ATTR(temp##num##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_hyst, set_temp_hyst, num - 1) - -sysfs_temp(1); -sysfs_temp(2); -sysfs_temp(3); -sysfs_temp(4); - -/* VID */ -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} - -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -/* VRM */ -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct asb100_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct asb100_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - data->vrm = val; - return count; -} - -/* Alarms */ -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); - -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); - -/* 1 PWM */ -static ssize_t show_pwm1(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", ASB100_PWM_FROM_REG(data->pwm & 0x0f)); -} - -static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm &= 0x80; /* keep the enable bit */ - data->pwm |= (0x0f & ASB100_PWM_TO_REG(val)); - asb100_write_value(client, ASB100_REG_PWM1, data->pwm); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_enable1(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct asb100_data *data = asb100_update_device(dev); - return sprintf(buf, "%d\n", (data->pwm & 0x80) ? 1 : 0); -} - -static ssize_t set_pwm_enable1(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct asb100_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm &= 0x0f; /* keep the duty cycle bits */ - data->pwm |= (val ? 0x80 : 0x00); - asb100_write_value(client, ASB100_REG_PWM1, data->pwm); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm1, set_pwm1); -static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, - show_pwm_enable1, set_pwm_enable1); - -static struct attribute *asb100_attributes[] = { - &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_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &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_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &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_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &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_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, - - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - &dev_attr_alarms.attr, - &dev_attr_pwm1.attr, - &dev_attr_pwm1_enable.attr, - - NULL -}; - -static const struct attribute_group asb100_group = { - .attrs = asb100_attributes, -}; - -static int asb100_detect_subclients(struct i2c_client *client) -{ - int i, id, err; - int address = client->addr; - unsigned short sc_addr[2]; - struct asb100_data *data = i2c_get_clientdata(client); - struct i2c_adapter *adapter = client->adapter; - - id = i2c_adapter_id(adapter); - - if (force_subclients[0] == id && force_subclients[1] == address) { - for (i = 2; i <= 3; i++) { - if (force_subclients[i] < 0x48 || - force_subclients[i] > 0x4f) { - dev_err(&client->dev, "invalid subclient " - "address %d; must be 0x48-0x4f\n", - force_subclients[i]); - err = -ENODEV; - goto ERROR_SC_2; - } - } - asb100_write_value(client, ASB100_REG_I2C_SUBADDR, - (force_subclients[2] & 0x07) | - ((force_subclients[3] & 0x07) << 4)); - sc_addr[0] = force_subclients[2]; - sc_addr[1] = force_subclients[3]; - } else { - int val = asb100_read_value(client, ASB100_REG_I2C_SUBADDR); - sc_addr[0] = 0x48 + (val & 0x07); - sc_addr[1] = 0x48 + ((val >> 4) & 0x07); - } - - if (sc_addr[0] == sc_addr[1]) { - dev_err(&client->dev, "duplicate addresses 0x%x " - "for subclients\n", sc_addr[0]); - err = -ENODEV; - goto ERROR_SC_2; - } - - data->lm75[0] = i2c_new_dummy(adapter, sc_addr[0]); - if (!data->lm75[0]) { - dev_err(&client->dev, "subclient %d registration " - "at address 0x%x failed.\n", 1, sc_addr[0]); - err = -ENOMEM; - goto ERROR_SC_2; - } - - data->lm75[1] = i2c_new_dummy(adapter, sc_addr[1]); - if (!data->lm75[1]) { - dev_err(&client->dev, "subclient %d registration " - "at address 0x%x failed.\n", 2, sc_addr[1]); - err = -ENOMEM; - goto ERROR_SC_3; - } - - return 0; - -/* Undo inits in case of errors */ -ERROR_SC_3: - i2c_unregister_device(data->lm75[0]); -ERROR_SC_2: - return err; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int asb100_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int val1, val2; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - pr_debug("detect failed, smbus byte data not supported!\n"); - return -ENODEV; - } - - val1 = i2c_smbus_read_byte_data(client, ASB100_REG_BANK); - val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); - - /* If we're in bank 0 */ - if ((!(val1 & 0x07)) && - /* Check for ASB100 ID (low byte) */ - (((!(val1 & 0x80)) && (val2 != 0x94)) || - /* Check for ASB100 ID (high byte ) */ - ((val1 & 0x80) && (val2 != 0x06)))) { - pr_debug("detect failed, bad chip id 0x%02x!\n", val2); - return -ENODEV; - } - - /* Put it now into bank 0 and Vendor ID High Byte */ - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, - (i2c_smbus_read_byte_data(client, ASB100_REG_BANK) & 0x78) - | 0x80); - - /* Determine the chip type. */ - val1 = i2c_smbus_read_byte_data(client, ASB100_REG_WCHIPID); - val2 = i2c_smbus_read_byte_data(client, ASB100_REG_CHIPMAN); - - if (val1 != 0x31 || val2 != 0x06) - return -ENODEV; - - strlcpy(info->type, "asb100", I2C_NAME_SIZE); - - return 0; -} - -static int asb100_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - struct asb100_data *data; - - data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); - if (!data) { - pr_debug("probe failed, kzalloc failed!\n"); - err = -ENOMEM; - goto ERROR0; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); - mutex_init(&data->update_lock); - - /* Attach secondary lm75 clients */ - err = asb100_detect_subclients(client); - if (err) - goto ERROR1; - - /* Initialize the chip */ - asb100_init_client(client); - - /* A few vars need to be filled upon startup */ - data->fan_min[0] = asb100_read_value(client, ASB100_REG_FAN_MIN(0)); - data->fan_min[1] = asb100_read_value(client, ASB100_REG_FAN_MIN(1)); - data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2)); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &asb100_group); - if (err) - goto ERROR3; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto ERROR4; - } - - return 0; - -ERROR4: - sysfs_remove_group(&client->dev.kobj, &asb100_group); -ERROR3: - i2c_unregister_device(data->lm75[1]); - i2c_unregister_device(data->lm75[0]); -ERROR1: - kfree(data); -ERROR0: - return err; -} - -static int asb100_remove(struct i2c_client *client) -{ - struct asb100_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &asb100_group); - - i2c_unregister_device(data->lm75[1]); - i2c_unregister_device(data->lm75[0]); - - kfree(data); - - return 0; -} - -/* - * The SMBus locks itself, usually, but nothing may access the chip between - * bank switches. - */ -static int asb100_read_value(struct i2c_client *client, u16 reg) -{ - struct asb100_data *data = i2c_get_clientdata(client); - struct i2c_client *cl; - int res, bank; - - mutex_lock(&data->lock); - - bank = (reg >> 8) & 0x0f; - if (bank > 2) - /* switch banks */ - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank); - - if (bank == 0 || bank > 2) { - res = i2c_smbus_read_byte_data(client, reg & 0xff); - } else { - /* switch to subclient */ - cl = data->lm75[bank - 1]; - - /* convert from ISA to LM75 I2C addresses */ - switch (reg & 0xff) { - case 0x50: /* TEMP */ - res = i2c_smbus_read_word_swapped(cl, 0); - break; - case 0x52: /* CONFIG */ - res = i2c_smbus_read_byte_data(cl, 1); - break; - case 0x53: /* HYST */ - res = i2c_smbus_read_word_swapped(cl, 2); - break; - case 0x55: /* MAX */ - default: - res = i2c_smbus_read_word_swapped(cl, 3); - break; - } - } - - if (bank > 2) - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - - mutex_unlock(&data->lock); - - return res; -} - -static void asb100_write_value(struct i2c_client *client, u16 reg, u16 value) -{ - struct asb100_data *data = i2c_get_clientdata(client); - struct i2c_client *cl; - int bank; - - mutex_lock(&data->lock); - - bank = (reg >> 8) & 0x0f; - if (bank > 2) - /* switch banks */ - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, bank); - - if (bank == 0 || bank > 2) { - i2c_smbus_write_byte_data(client, reg & 0xff, value & 0xff); - } else { - /* switch to subclient */ - cl = data->lm75[bank - 1]; - - /* convert from ISA to LM75 I2C addresses */ - switch (reg & 0xff) { - case 0x52: /* CONFIG */ - i2c_smbus_write_byte_data(cl, 1, value & 0xff); - break; - case 0x53: /* HYST */ - i2c_smbus_write_word_swapped(cl, 2, value); - break; - case 0x55: /* MAX */ - i2c_smbus_write_word_swapped(cl, 3, value); - break; - } - } - - if (bank > 2) - i2c_smbus_write_byte_data(client, ASB100_REG_BANK, 0); - - mutex_unlock(&data->lock); -} - -static void asb100_init_client(struct i2c_client *client) -{ - struct asb100_data *data = i2c_get_clientdata(client); - - data->vrm = vid_which_vrm(); - - /* Start monitoring */ - asb100_write_value(client, ASB100_REG_CONFIG, - (asb100_read_value(client, ASB100_REG_CONFIG) & 0xf7) | 0x01); -} - -static struct asb100_data *asb100_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct asb100_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - - dev_dbg(&client->dev, "starting device update...\n"); - - /* 7 voltage inputs */ - for (i = 0; i < 7; i++) { - data->in[i] = asb100_read_value(client, - ASB100_REG_IN(i)); - data->in_min[i] = asb100_read_value(client, - ASB100_REG_IN_MIN(i)); - data->in_max[i] = asb100_read_value(client, - ASB100_REG_IN_MAX(i)); - } - - /* 3 fan inputs */ - for (i = 0; i < 3; i++) { - data->fan[i] = asb100_read_value(client, - ASB100_REG_FAN(i)); - data->fan_min[i] = asb100_read_value(client, - ASB100_REG_FAN_MIN(i)); - } - - /* 4 temperature inputs */ - for (i = 1; i <= 4; i++) { - data->temp[i-1] = asb100_read_value(client, - ASB100_REG_TEMP(i)); - data->temp_max[i-1] = asb100_read_value(client, - ASB100_REG_TEMP_MAX(i)); - data->temp_hyst[i-1] = asb100_read_value(client, - ASB100_REG_TEMP_HYST(i)); - } - - /* VID and fan divisors */ - i = asb100_read_value(client, ASB100_REG_VID_FANDIV); - data->vid = i & 0x0f; - data->vid |= (asb100_read_value(client, - ASB100_REG_CHIPID) & 0x01) << 4; - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = (i >> 6) & 0x03; - data->fan_div[2] = (asb100_read_value(client, - ASB100_REG_PIN) >> 6) & 0x03; - - /* PWM */ - data->pwm = asb100_read_value(client, ASB100_REG_PWM1); - - /* alarms */ - data->alarms = asb100_read_value(client, ASB100_REG_ALARM1) + - (asb100_read_value(client, ASB100_REG_ALARM2) << 8); - - data->last_updated = jiffies; - data->valid = 1; - - dev_dbg(&client->dev, "... device update complete\n"); - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(asb100_driver); - -MODULE_AUTHOR("Mark M. Hoffman "); -MODULE_DESCRIPTION("ASB100 Bach driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/asc7621.c b/ANDROID_3.4.5/drivers/hwmon/asc7621.c deleted file mode 100644 index 7caa2429..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/asc7621.c +++ /dev/null @@ -1,1249 +0,0 @@ -/* - * asc7621.c - Part of lm_sensors, Linux kernel modules for hardware monitoring - * Copyright (c) 2007, 2010 George Joseph - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x2c, 0x2d, 0x2e, I2C_CLIENT_END -}; - -enum asc7621_type { - asc7621, - asc7621a -}; - -#define INTERVAL_HIGH (HZ + HZ / 2) -#define INTERVAL_LOW (1 * 60 * HZ) -#define PRI_NONE 0 -#define PRI_LOW 1 -#define PRI_HIGH 2 -#define FIRST_CHIP asc7621 -#define LAST_CHIP asc7621a - -struct asc7621_chip { - char *name; - enum asc7621_type chip_type; - u8 company_reg; - u8 company_id; - u8 verstep_reg; - u8 verstep_id; - const unsigned short *addresses; -}; - -static struct asc7621_chip asc7621_chips[] = { - { - .name = "asc7621", - .chip_type = asc7621, - .company_reg = 0x3e, - .company_id = 0x61, - .verstep_reg = 0x3f, - .verstep_id = 0x6c, - .addresses = normal_i2c, - }, - { - .name = "asc7621a", - .chip_type = asc7621a, - .company_reg = 0x3e, - .company_id = 0x61, - .verstep_reg = 0x3f, - .verstep_id = 0x6d, - .addresses = normal_i2c, - }, -}; - -/* - * Defines the highest register to be used, not the count. - * The actual count will probably be smaller because of gaps - * in the implementation (unused register locations). - * This define will safely set the array size of both the parameter - * and data arrays. - * This comes from the data sheet register description table. - */ -#define LAST_REGISTER 0xff - -struct asc7621_data { - struct i2c_client client; - struct device *class_dev; - struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ - unsigned long last_high_reading; /* In jiffies */ - unsigned long last_low_reading; /* In jiffies */ - /* - * Registers we care about occupy the corresponding index - * in the array. Registers we don't care about are left - * at 0. - */ - u8 reg[LAST_REGISTER + 1]; -}; - -/* - * Macro to get the parent asc7621_param structure - * from a sensor_device_attribute passed into the - * show/store functions. - */ -#define to_asc7621_param(_sda) \ - container_of(_sda, struct asc7621_param, sda) - -/* - * Each parameter to be retrieved needs an asc7621_param structure - * allocated. It contains the sensor_device_attribute structure - * and the control info needed to retrieve the value from the register map. - */ -struct asc7621_param { - struct sensor_device_attribute sda; - u8 priority; - u8 msb[3]; - u8 lsb[3]; - u8 mask[3]; - u8 shift[3]; -}; - -/* - * This is the map that ultimately indicates whether we'll be - * retrieving a register value or not, and at what frequency. - */ -static u8 asc7621_register_priorities[255]; - -static struct asc7621_data *asc7621_update_device(struct device *dev); - -static inline u8 read_byte(struct i2c_client *client, u8 reg) -{ - int res = i2c_smbus_read_byte_data(client, reg); - if (res < 0) { - dev_err(&client->dev, - "Unable to read from register 0x%02x.\n", reg); - return 0; - }; - return res & 0xff; -} - -static inline int write_byte(struct i2c_client *client, u8 reg, u8 data) -{ - int res = i2c_smbus_write_byte_data(client, reg, data); - if (res < 0) { - dev_err(&client->dev, - "Unable to write value 0x%02x to register 0x%02x.\n", - data, reg); - }; - return res; -} - -/* - * Data Handlers - * Each function handles the formatting, storage - * and retrieval of like parameters. - */ - -#define SETUP_SHOW_data_param(d, a) \ - struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ - struct asc7621_data *data = asc7621_update_device(d); \ - struct asc7621_param *param = to_asc7621_param(sda) - -#define SETUP_STORE_data_param(d, a) \ - struct sensor_device_attribute *sda = to_sensor_dev_attr(a); \ - struct i2c_client *client = to_i2c_client(d); \ - struct asc7621_data *data = i2c_get_clientdata(client); \ - struct asc7621_param *param = to_asc7621_param(sda) - -/* - * u8 is just what it sounds like...an unsigned byte with no - * special formatting. - */ -static ssize_t show_u8(struct device *dev, struct device_attribute *attr, - char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - - return sprintf(buf, "%u\n", data->reg[param->msb[0]]); -} - -static ssize_t store_u8(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - reqval = SENSORS_LIMIT(reqval, 0, 255); - - mutex_lock(&data->update_lock); - data->reg[param->msb[0]] = reqval; - write_byte(client, param->msb[0], reqval); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Many of the config values occupy only a few bits of a register. - */ -static ssize_t show_bitmask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - - return sprintf(buf, "%u\n", - (data->reg[param->msb[0]] >> param-> - shift[0]) & param->mask[0]); -} - -static ssize_t store_bitmask(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - u8 currval; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - reqval = SENSORS_LIMIT(reqval, 0, param->mask[0]); - - reqval = (reqval & param->mask[0]) << param->shift[0]; - - mutex_lock(&data->update_lock); - currval = read_byte(client, param->msb[0]); - reqval |= (currval & ~(param->mask[0] << param->shift[0])); - data->reg[param->msb[0]] = reqval; - write_byte(client, param->msb[0], reqval); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * 16 bit fan rpm values - * reported by the device as the number of 11.111us periods (90khz) - * between full fan rotations. Therefore... - * RPM = (90000 * 60) / register value - */ -static ssize_t show_fan16(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u16 regval; - - mutex_lock(&data->update_lock); - regval = (data->reg[param->msb[0]] << 8) | data->reg[param->lsb[0]]; - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%u\n", - (regval == 0 ? -1 : (regval) == - 0xffff ? 0 : 5400000 / regval)); -} - -static ssize_t store_fan16(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - /* - * If a minimum RPM of zero is requested, then we set the register to - * 0xffff. This value allows the fan to be stopped completely without - * generating an alarm. - */ - reqval = - (reqval <= 0 ? 0xffff : SENSORS_LIMIT(5400000 / reqval, 0, 0xfffe)); - - mutex_lock(&data->update_lock); - data->reg[param->msb[0]] = (reqval >> 8) & 0xff; - data->reg[param->lsb[0]] = reqval & 0xff; - write_byte(client, param->msb[0], data->reg[param->msb[0]]); - write_byte(client, param->lsb[0], data->reg[param->lsb[0]]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Voltages are scaled in the device so that the nominal voltage - * is 3/4ths of the 0-255 range (i.e. 192). - * If all voltages are 'normal' then all voltage registers will - * read 0xC0. - * - * The data sheet provides us with the 3/4 scale value for each voltage - * which is stored in in_scaling. The sda->index parameter value provides - * the index into in_scaling. - * - * NOTE: The chip expects the first 2 inputs be 2.5 and 2.25 volts - * respectively. That doesn't mean that's what the motherboard provides. :) - */ - -static int asc7621_in_scaling[] = { - 2500, 2250, 3300, 5000, 12000 -}; - -static ssize_t show_in10(struct device *dev, struct device_attribute *attr, - char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u16 regval; - u8 nr = sda->index; - - mutex_lock(&data->update_lock); - regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]); - mutex_unlock(&data->update_lock); - - /* The LSB value is a 2-bit scaling of the MSB's LSbit value. */ - regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2); - - return sprintf(buf, "%u\n", regval); -} - -/* 8 bit voltage values (the mins and maxs) */ -static ssize_t show_in8(struct device *dev, struct device_attribute *attr, - char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 nr = sda->index; - - return sprintf(buf, "%u\n", - ((data->reg[param->msb[0]] * - asc7621_in_scaling[nr]) / 0xc0)); -} - -static ssize_t store_in8(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - u8 nr = sda->index; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - reqval = SENSORS_LIMIT(reqval, 0, 0xffff); - - reqval = reqval * 0xc0 / asc7621_in_scaling[nr]; - - reqval = SENSORS_LIMIT(reqval, 0, 0xff); - - mutex_lock(&data->update_lock); - data->reg[param->msb[0]] = reqval; - write_byte(client, param->msb[0], reqval); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp8(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - - return sprintf(buf, "%d\n", ((s8) data->reg[param->msb[0]]) * 1000); -} - -static ssize_t store_temp8(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - s8 temp; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - reqval = SENSORS_LIMIT(reqval, -127000, 127000); - - temp = reqval / 1000; - - mutex_lock(&data->update_lock); - data->reg[param->msb[0]] = temp; - write_byte(client, param->msb[0], temp); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Temperatures that occupy 2 bytes always have the whole - * number of degrees in the MSB with some part of the LSB - * indicating fractional degrees. - */ - -/* mmmmmmmm.llxxxxxx */ -static ssize_t show_temp10(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 msb, lsb; - int temp; - - mutex_lock(&data->update_lock); - msb = data->reg[param->msb[0]]; - lsb = (data->reg[param->lsb[0]] >> 6) & 0x03; - temp = (((s8) msb) * 1000) + (lsb * 250); - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", temp); -} - -/* mmmmmm.ll */ -static ssize_t show_temp62(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 regval = data->reg[param->msb[0]]; - int temp = ((s8) (regval & 0xfc) * 1000) + ((regval & 0x03) * 250); - - return sprintf(buf, "%d\n", temp); -} - -static ssize_t store_temp62(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval, i, f; - s8 temp; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - reqval = SENSORS_LIMIT(reqval, -32000, 31750); - i = reqval / 1000; - f = reqval - (i * 1000); - temp = i << 2; - temp |= f / 250; - - mutex_lock(&data->update_lock); - data->reg[param->msb[0]] = temp; - write_byte(client, param->msb[0], temp); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * The aSC7621 doesn't provide an "auto_point2". Instead, you - * specify the auto_point1 and a range. To keep with the sysfs - * hwmon specs, we synthesize the auto_point_2 from them. - */ - -static u32 asc7621_range_map[] = { - 2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000, - 13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000, -}; - -static ssize_t show_ap2_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - long auto_point1; - u8 regval; - int temp; - - mutex_lock(&data->update_lock); - auto_point1 = ((s8) data->reg[param->msb[1]]) * 1000; - regval = - ((data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]); - temp = auto_point1 + asc7621_range_map[SENSORS_LIMIT(regval, 0, 15)]; - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", temp); - -} - -static ssize_t store_ap2_temp(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval, auto_point1; - int i; - u8 currval, newval = 0; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - mutex_lock(&data->update_lock); - auto_point1 = data->reg[param->msb[1]] * 1000; - reqval = SENSORS_LIMIT(reqval, auto_point1 + 2000, auto_point1 + 80000); - - for (i = ARRAY_SIZE(asc7621_range_map) - 1; i >= 0; i--) { - if (reqval >= auto_point1 + asc7621_range_map[i]) { - newval = i; - break; - } - } - - newval = (newval & param->mask[0]) << param->shift[0]; - currval = read_byte(client, param->msb[0]); - newval |= (currval & ~(param->mask[0] << param->shift[0])); - data->reg[param->msb[0]] = newval; - write_byte(client, param->msb[0], newval); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_ac(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 config, altbit, regval; - u8 map[] = { - 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10, - 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f - }; - - mutex_lock(&data->update_lock); - config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; - altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; - regval = config | (altbit << 3); - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%u\n", map[SENSORS_LIMIT(regval, 0, 15)]); -} - -static ssize_t store_pwm_ac(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - unsigned long reqval; - u8 currval, config, altbit, newval; - u16 map[] = { - 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06, - 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, - 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, - }; - - if (kstrtoul(buf, 10, &reqval)) - return -EINVAL; - - if (reqval > 31) - return -EINVAL; - - reqval = map[reqval]; - if (reqval == 0xff) - return -EINVAL; - - config = reqval & 0x07; - altbit = (reqval >> 3) & 0x01; - - config = (config & param->mask[0]) << param->shift[0]; - altbit = (altbit & param->mask[1]) << param->shift[1]; - - mutex_lock(&data->update_lock); - currval = read_byte(client, param->msb[0]); - newval = config | (currval & ~(param->mask[0] << param->shift[0])); - newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); - data->reg[param->msb[0]] = newval; - write_byte(client, param->msb[0], newval); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 config, altbit, minoff, val, newval; - - mutex_lock(&data->update_lock); - config = (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; - altbit = (data->reg[param->msb[1]] >> param->shift[1]) & param->mask[1]; - minoff = (data->reg[param->msb[2]] >> param->shift[2]) & param->mask[2]; - mutex_unlock(&data->update_lock); - - val = config | (altbit << 3); - newval = 0; - - if (val == 3 || val >= 10) - newval = 255; - else if (val == 4) - newval = 0; - else if (val == 7) - newval = 1; - else if (minoff == 1) - newval = 2; - else - newval = 3; - - return sprintf(buf, "%u\n", newval); -} - -static ssize_t store_pwm_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - u8 currval, config, altbit, newval, minoff = 255; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - switch (reqval) { - case 0: - newval = 0x04; - break; - case 1: - newval = 0x07; - break; - case 2: - newval = 0x00; - minoff = 1; - break; - case 3: - newval = 0x00; - minoff = 0; - break; - case 255: - newval = 0x03; - break; - default: - return -EINVAL; - } - - config = newval & 0x07; - altbit = (newval >> 3) & 0x01; - - mutex_lock(&data->update_lock); - config = (config & param->mask[0]) << param->shift[0]; - altbit = (altbit & param->mask[1]) << param->shift[1]; - currval = read_byte(client, param->msb[0]); - newval = config | (currval & ~(param->mask[0] << param->shift[0])); - newval = altbit | (newval & ~(param->mask[1] << param->shift[1])); - data->reg[param->msb[0]] = newval; - write_byte(client, param->msb[0], newval); - if (minoff < 255) { - minoff = (minoff & param->mask[2]) << param->shift[2]; - currval = read_byte(client, param->msb[2]); - newval = - minoff | (currval & ~(param->mask[2] << param->shift[2])); - data->reg[param->msb[2]] = newval; - write_byte(client, param->msb[2], newval); - } - mutex_unlock(&data->update_lock); - return count; -} - -static u32 asc7621_pwm_freq_map[] = { - 10, 15, 23, 30, 38, 47, 62, 94, - 23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000 -}; - -static ssize_t show_pwm_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 regval = - (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; - - regval = SENSORS_LIMIT(regval, 0, 15); - - return sprintf(buf, "%u\n", asc7621_pwm_freq_map[regval]); -} - -static ssize_t store_pwm_freq(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - unsigned long reqval; - u8 currval, newval = 255; - int i; - - if (kstrtoul(buf, 10, &reqval)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(asc7621_pwm_freq_map); i++) { - if (reqval == asc7621_pwm_freq_map[i]) { - newval = i; - break; - } - } - if (newval == 255) - return -EINVAL; - - newval = (newval & param->mask[0]) << param->shift[0]; - - mutex_lock(&data->update_lock); - currval = read_byte(client, param->msb[0]); - newval |= (currval & ~(param->mask[0] << param->shift[0])); - data->reg[param->msb[0]] = newval; - write_byte(client, param->msb[0], newval); - mutex_unlock(&data->update_lock); - return count; -} - -static u32 asc7621_pwm_auto_spinup_map[] = { - 0, 100, 250, 400, 700, 1000, 2000, 4000 -}; - -static ssize_t show_pwm_ast(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 regval = - (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; - - regval = SENSORS_LIMIT(regval, 0, 7); - - return sprintf(buf, "%u\n", asc7621_pwm_auto_spinup_map[regval]); - -} - -static ssize_t store_pwm_ast(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - u8 currval, newval = 255; - u32 i; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(asc7621_pwm_auto_spinup_map); i++) { - if (reqval == asc7621_pwm_auto_spinup_map[i]) { - newval = i; - break; - } - } - if (newval == 255) - return -EINVAL; - - newval = (newval & param->mask[0]) << param->shift[0]; - - mutex_lock(&data->update_lock); - currval = read_byte(client, param->msb[0]); - newval |= (currval & ~(param->mask[0] << param->shift[0])); - data->reg[param->msb[0]] = newval; - write_byte(client, param->msb[0], newval); - mutex_unlock(&data->update_lock); - return count; -} - -static u32 asc7621_temp_smoothing_time_map[] = { - 35000, 17600, 11800, 7000, 4400, 3000, 1600, 800 -}; - -static ssize_t show_temp_st(struct device *dev, - struct device_attribute *attr, char *buf) -{ - SETUP_SHOW_data_param(dev, attr); - u8 regval = - (data->reg[param->msb[0]] >> param->shift[0]) & param->mask[0]; - regval = SENSORS_LIMIT(regval, 0, 7); - - return sprintf(buf, "%u\n", asc7621_temp_smoothing_time_map[regval]); -} - -static ssize_t store_temp_st(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - SETUP_STORE_data_param(dev, attr); - long reqval; - u8 currval, newval = 255; - u32 i; - - if (kstrtol(buf, 10, &reqval)) - return -EINVAL; - - for (i = 0; i < ARRAY_SIZE(asc7621_temp_smoothing_time_map); i++) { - if (reqval == asc7621_temp_smoothing_time_map[i]) { - newval = i; - break; - } - } - - if (newval == 255) - return -EINVAL; - - newval = (newval & param->mask[0]) << param->shift[0]; - - mutex_lock(&data->update_lock); - currval = read_byte(client, param->msb[0]); - newval |= (currval & ~(param->mask[0] << param->shift[0])); - data->reg[param->msb[0]] = newval; - write_byte(client, param->msb[0], newval); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * End of data handlers - * - * These defines do nothing more than make the table easier - * to read when wrapped at column 80. - */ - -/* - * Creates a variable length array inititalizer. - * VAA(1,3,5,7) would produce {1,3,5,7} - */ -#define VAA(args...) {args} - -#define PREAD(name, n, pri, rm, rl, m, s, r) \ - {.sda = SENSOR_ATTR(name, S_IRUGO, show_##r, NULL, n), \ - .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ - .shift[0] = s,} - -#define PWRITE(name, n, pri, rm, rl, m, s, r) \ - {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ - .priority = pri, .msb[0] = rm, .lsb[0] = rl, .mask[0] = m, \ - .shift[0] = s,} - -/* - * PWRITEM assumes that the initializers for the .msb, .lsb, .mask and .shift - * were created using the VAA macro. - */ -#define PWRITEM(name, n, pri, rm, rl, m, s, r) \ - {.sda = SENSOR_ATTR(name, S_IRUGO | S_IWUSR, show_##r, store_##r, n), \ - .priority = pri, .msb = rm, .lsb = rl, .mask = m, .shift = s,} - -static struct asc7621_param asc7621_params[] = { - PREAD(in0_input, 0, PRI_HIGH, 0x20, 0x13, 0, 0, in10), - PREAD(in1_input, 1, PRI_HIGH, 0x21, 0x18, 0, 0, in10), - PREAD(in2_input, 2, PRI_HIGH, 0x22, 0x11, 0, 0, in10), - PREAD(in3_input, 3, PRI_HIGH, 0x23, 0x12, 0, 0, in10), - PREAD(in4_input, 4, PRI_HIGH, 0x24, 0x14, 0, 0, in10), - - PWRITE(in0_min, 0, PRI_LOW, 0x44, 0, 0, 0, in8), - PWRITE(in1_min, 1, PRI_LOW, 0x46, 0, 0, 0, in8), - PWRITE(in2_min, 2, PRI_LOW, 0x48, 0, 0, 0, in8), - PWRITE(in3_min, 3, PRI_LOW, 0x4a, 0, 0, 0, in8), - PWRITE(in4_min, 4, PRI_LOW, 0x4c, 0, 0, 0, in8), - - PWRITE(in0_max, 0, PRI_LOW, 0x45, 0, 0, 0, in8), - PWRITE(in1_max, 1, PRI_LOW, 0x47, 0, 0, 0, in8), - PWRITE(in2_max, 2, PRI_LOW, 0x49, 0, 0, 0, in8), - PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), - PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), - - PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask), - PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask), - PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask), - PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask), - PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask), - - PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), - PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), - PREAD(fan3_input, 2, PRI_HIGH, 0x2d, 0x2c, 0, 0, fan16), - PREAD(fan4_input, 3, PRI_HIGH, 0x2f, 0x2e, 0, 0, fan16), - - PWRITE(fan1_min, 0, PRI_LOW, 0x55, 0x54, 0, 0, fan16), - PWRITE(fan2_min, 1, PRI_LOW, 0x57, 0x56, 0, 0, fan16), - PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), - PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), - - PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask), - PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask), - PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask), - PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask), - - PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), - PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), - PREAD(temp3_input, 2, PRI_HIGH, 0x27, 0x16, 0, 0, temp10), - PREAD(temp4_input, 3, PRI_HIGH, 0x33, 0x17, 0, 0, temp10), - PREAD(temp5_input, 4, PRI_HIGH, 0xf7, 0xf6, 0, 0, temp10), - PREAD(temp6_input, 5, PRI_HIGH, 0xf9, 0xf8, 0, 0, temp10), - PREAD(temp7_input, 6, PRI_HIGH, 0xfb, 0xfa, 0, 0, temp10), - PREAD(temp8_input, 7, PRI_HIGH, 0xfd, 0xfc, 0, 0, temp10), - - PWRITE(temp1_min, 0, PRI_LOW, 0x4e, 0, 0, 0, temp8), - PWRITE(temp2_min, 1, PRI_LOW, 0x50, 0, 0, 0, temp8), - PWRITE(temp3_min, 2, PRI_LOW, 0x52, 0, 0, 0, temp8), - PWRITE(temp4_min, 3, PRI_LOW, 0x34, 0, 0, 0, temp8), - - PWRITE(temp1_max, 0, PRI_LOW, 0x4f, 0, 0, 0, temp8), - PWRITE(temp2_max, 1, PRI_LOW, 0x51, 0, 0, 0, temp8), - PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), - PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), - - PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask), - PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask), - PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask), - PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask), - - PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), - PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), - PWRITE(temp3_source, 2, PRI_LOW, 0x03, 0, 0x07, 4, bitmask), - PWRITE(temp4_source, 3, PRI_LOW, 0x03, 0, 0x07, 0, bitmask), - - PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), - PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), - PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask), - PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), - - PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), - PWRITE(temp2_smoothing_time, 1, PRI_LOW, 0x63, 0, 0x07, 4, temp_st), - PWRITE(temp3_smoothing_time, 2, PRI_LOW, 0x63, 0, 0x07, 0, temp_st), - PWRITE(temp4_smoothing_time, 3, PRI_LOW, 0x3c, 0, 0x07, 0, temp_st), - - PWRITE(temp1_auto_point1_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, - bitmask), - PWRITE(temp2_auto_point1_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, - bitmask), - PWRITE(temp3_auto_point1_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, - bitmask), - PWRITE(temp4_auto_point1_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, - bitmask), - - PREAD(temp1_auto_point2_temp_hyst, 0, PRI_LOW, 0x6d, 0, 0x0f, 4, - bitmask), - PREAD(temp2_auto_point2_temp_hyst, 1, PRI_LOW, 0x6d, 0, 0x0f, 0, - bitmask), - PREAD(temp3_auto_point2_temp_hyst, 2, PRI_LOW, 0x6e, 0, 0x0f, 4, - bitmask), - PREAD(temp4_auto_point2_temp_hyst, 3, PRI_LOW, 0x6e, 0, 0x0f, 0, - bitmask), - - PWRITE(temp1_auto_point1_temp, 0, PRI_LOW, 0x67, 0, 0, 0, temp8), - PWRITE(temp2_auto_point1_temp, 1, PRI_LOW, 0x68, 0, 0, 0, temp8), - PWRITE(temp3_auto_point1_temp, 2, PRI_LOW, 0x69, 0, 0, 0, temp8), - PWRITE(temp4_auto_point1_temp, 3, PRI_LOW, 0x3b, 0, 0, 0, temp8), - - PWRITEM(temp1_auto_point2_temp, 0, PRI_LOW, VAA(0x5f, 0x67), VAA(0), - VAA(0x0f), VAA(4), ap2_temp), - PWRITEM(temp2_auto_point2_temp, 1, PRI_LOW, VAA(0x60, 0x68), VAA(0), - VAA(0x0f), VAA(4), ap2_temp), - PWRITEM(temp3_auto_point2_temp, 2, PRI_LOW, VAA(0x61, 0x69), VAA(0), - VAA(0x0f), VAA(4), ap2_temp), - PWRITEM(temp4_auto_point2_temp, 3, PRI_LOW, VAA(0x3c, 0x3b), VAA(0), - VAA(0x0f), VAA(4), ap2_temp), - - PWRITE(temp1_crit, 0, PRI_LOW, 0x6a, 0, 0, 0, temp8), - PWRITE(temp2_crit, 1, PRI_LOW, 0x6b, 0, 0, 0, temp8), - PWRITE(temp3_crit, 2, PRI_LOW, 0x6c, 0, 0, 0, temp8), - PWRITE(temp4_crit, 3, PRI_LOW, 0x3d, 0, 0, 0, temp8), - - PWRITE(temp5_enable, 4, PRI_LOW, 0x0e, 0, 0x01, 0, bitmask), - PWRITE(temp6_enable, 5, PRI_LOW, 0x0e, 0, 0x01, 1, bitmask), - PWRITE(temp7_enable, 6, PRI_LOW, 0x0e, 0, 0x01, 2, bitmask), - PWRITE(temp8_enable, 7, PRI_LOW, 0x0e, 0, 0x01, 3, bitmask), - - PWRITE(remote1_offset, 0, PRI_LOW, 0x1c, 0, 0, 0, temp62), - PWRITE(remote2_offset, 1, PRI_LOW, 0x1d, 0, 0, 0, temp62), - - PWRITE(pwm1, 0, PRI_HIGH, 0x30, 0, 0, 0, u8), - PWRITE(pwm2, 1, PRI_HIGH, 0x31, 0, 0, 0, u8), - PWRITE(pwm3, 2, PRI_HIGH, 0x32, 0, 0, 0, u8), - - PWRITE(pwm1_invert, 0, PRI_LOW, 0x5c, 0, 0x01, 4, bitmask), - PWRITE(pwm2_invert, 1, PRI_LOW, 0x5d, 0, 0x01, 4, bitmask), - PWRITE(pwm3_invert, 2, PRI_LOW, 0x5e, 0, 0x01, 4, bitmask), - - PWRITEM(pwm1_enable, 0, PRI_LOW, VAA(0x5c, 0x5c, 0x62), VAA(0, 0, 0), - VAA(0x07, 0x01, 0x01), VAA(5, 3, 5), pwm_enable), - PWRITEM(pwm2_enable, 1, PRI_LOW, VAA(0x5d, 0x5d, 0x62), VAA(0, 0, 0), - VAA(0x07, 0x01, 0x01), VAA(5, 3, 6), pwm_enable), - PWRITEM(pwm3_enable, 2, PRI_LOW, VAA(0x5e, 0x5e, 0x62), VAA(0, 0, 0), - VAA(0x07, 0x01, 0x01), VAA(5, 3, 7), pwm_enable), - - PWRITEM(pwm1_auto_channels, 0, PRI_LOW, VAA(0x5c, 0x5c), VAA(0, 0), - VAA(0x07, 0x01), VAA(5, 3), pwm_ac), - PWRITEM(pwm2_auto_channels, 1, PRI_LOW, VAA(0x5d, 0x5d), VAA(0, 0), - VAA(0x07, 0x01), VAA(5, 3), pwm_ac), - PWRITEM(pwm3_auto_channels, 2, PRI_LOW, VAA(0x5e, 0x5e), VAA(0, 0), - VAA(0x07, 0x01), VAA(5, 3), pwm_ac), - - PWRITE(pwm1_auto_point1_pwm, 0, PRI_LOW, 0x64, 0, 0, 0, u8), - PWRITE(pwm2_auto_point1_pwm, 1, PRI_LOW, 0x65, 0, 0, 0, u8), - PWRITE(pwm3_auto_point1_pwm, 2, PRI_LOW, 0x66, 0, 0, 0, u8), - - PWRITE(pwm1_auto_point2_pwm, 0, PRI_LOW, 0x38, 0, 0, 0, u8), - PWRITE(pwm2_auto_point2_pwm, 1, PRI_LOW, 0x39, 0, 0, 0, u8), - PWRITE(pwm3_auto_point2_pwm, 2, PRI_LOW, 0x3a, 0, 0, 0, u8), - - PWRITE(pwm1_freq, 0, PRI_LOW, 0x5f, 0, 0x0f, 0, pwm_freq), - PWRITE(pwm2_freq, 1, PRI_LOW, 0x60, 0, 0x0f, 0, pwm_freq), - PWRITE(pwm3_freq, 2, PRI_LOW, 0x61, 0, 0x0f, 0, pwm_freq), - - PREAD(pwm1_auto_zone_assigned, 0, PRI_LOW, 0, 0, 0x03, 2, bitmask), - PREAD(pwm2_auto_zone_assigned, 1, PRI_LOW, 0, 0, 0x03, 4, bitmask), - PREAD(pwm3_auto_zone_assigned, 2, PRI_LOW, 0, 0, 0x03, 6, bitmask), - - PWRITE(pwm1_auto_spinup_time, 0, PRI_LOW, 0x5c, 0, 0x07, 0, pwm_ast), - PWRITE(pwm2_auto_spinup_time, 1, PRI_LOW, 0x5d, 0, 0x07, 0, pwm_ast), - PWRITE(pwm3_auto_spinup_time, 2, PRI_LOW, 0x5e, 0, 0x07, 0, pwm_ast), - - PWRITE(peci_enable, 0, PRI_LOW, 0x40, 0, 0x01, 4, bitmask), - PWRITE(peci_avg, 0, PRI_LOW, 0x36, 0, 0x07, 0, bitmask), - PWRITE(peci_domain, 0, PRI_LOW, 0x36, 0, 0x01, 3, bitmask), - PWRITE(peci_legacy, 0, PRI_LOW, 0x36, 0, 0x01, 4, bitmask), - PWRITE(peci_diode, 0, PRI_LOW, 0x0e, 0, 0x07, 4, bitmask), - PWRITE(peci_4domain, 0, PRI_LOW, 0x0e, 0, 0x01, 4, bitmask), - -}; - -static struct asc7621_data *asc7621_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct asc7621_data *data = i2c_get_clientdata(client); - int i; - -/* - * The asc7621 chips guarantee consistent reads of multi-byte values - * regardless of the order of the reads. No special logic is needed - * so we can just read the registers in whatever order they appear - * in the asc7621_params array. - */ - - mutex_lock(&data->update_lock); - - /* Read all the high priority registers */ - - if (!data->valid || - time_after(jiffies, data->last_high_reading + INTERVAL_HIGH)) { - - for (i = 0; i < ARRAY_SIZE(asc7621_register_priorities); i++) { - if (asc7621_register_priorities[i] == PRI_HIGH) { - data->reg[i] = - i2c_smbus_read_byte_data(client, i) & 0xff; - } - } - data->last_high_reading = jiffies; - }; /* last_reading */ - - /* Read all the low priority registers. */ - - if (!data->valid || - time_after(jiffies, data->last_low_reading + INTERVAL_LOW)) { - - for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { - if (asc7621_register_priorities[i] == PRI_LOW) { - data->reg[i] = - i2c_smbus_read_byte_data(client, i) & 0xff; - } - } - data->last_low_reading = jiffies; - }; /* last_reading */ - - data->valid = 1; - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Standard detection and initialization below - * - * Helper function that checks if an address is valid - * for a particular chip. - */ - -static inline int valid_address_for_chip(int chip_type, int address) -{ - int i; - - for (i = 0; asc7621_chips[chip_type].addresses[i] != I2C_CLIENT_END; - i++) { - if (asc7621_chips[chip_type].addresses[i] == address) - return 1; - } - return 0; -} - -static void asc7621_init_client(struct i2c_client *client) -{ - int value; - - /* Warn if part was not "READY" */ - - value = read_byte(client, 0x40); - - if (value & 0x02) { - dev_err(&client->dev, - "Client (%d,0x%02x) config is locked.\n", - i2c_adapter_id(client->adapter), client->addr); - }; - if (!(value & 0x04)) { - dev_err(&client->dev, "Client (%d,0x%02x) is not ready.\n", - i2c_adapter_id(client->adapter), client->addr); - }; - -/* - * Start monitoring - * - * Try to clear LOCK, Set START, save everything else - */ - value = (value & ~0x02) | 0x01; - write_byte(client, 0x40, value & 0xff); - -} - -static int -asc7621_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct asc7621_data *data; - int i, err; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - data = kzalloc(sizeof(struct asc7621_data), GFP_KERNEL); - if (data == NULL) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Initialize the asc7621 chip */ - asc7621_init_client(client); - - /* Create the sysfs entries */ - for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { - err = - device_create_file(&client->dev, - &(asc7621_params[i].sda.dev_attr)); - if (err) - goto exit_remove; - } - - data->class_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->class_dev)) { - err = PTR_ERR(data->class_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { - device_remove_file(&client->dev, - &(asc7621_params[i].sda.dev_attr)); - } - - kfree(data); - return err; -} - -static int asc7621_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int company, verstep, chip_index; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - for (chip_index = FIRST_CHIP; chip_index <= LAST_CHIP; chip_index++) { - - if (!valid_address_for_chip(chip_index, client->addr)) - continue; - - company = read_byte(client, - asc7621_chips[chip_index].company_reg); - verstep = read_byte(client, - asc7621_chips[chip_index].verstep_reg); - - if (company == asc7621_chips[chip_index].company_id && - verstep == asc7621_chips[chip_index].verstep_id) { - strlcpy(info->type, asc7621_chips[chip_index].name, - I2C_NAME_SIZE); - - dev_info(&adapter->dev, "Matched %s at 0x%02x\n", - asc7621_chips[chip_index].name, client->addr); - return 0; - } - } - - return -ENODEV; -} - -static int asc7621_remove(struct i2c_client *client) -{ - struct asc7621_data *data = i2c_get_clientdata(client); - int i; - - hwmon_device_unregister(data->class_dev); - - for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { - device_remove_file(&client->dev, - &(asc7621_params[i].sda.dev_attr)); - } - - kfree(data); - return 0; -} - -static const struct i2c_device_id asc7621_id[] = { - {"asc7621", asc7621}, - {"asc7621a", asc7621a}, - {}, -}; - -MODULE_DEVICE_TABLE(i2c, asc7621_id); - -static struct i2c_driver asc7621_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "asc7621", - }, - .probe = asc7621_probe, - .remove = asc7621_remove, - .id_table = asc7621_id, - .detect = asc7621_detect, - .address_list = normal_i2c, -}; - -static int __init sm_asc7621_init(void) -{ - int i, j; -/* - * Collect all the registers needed into a single array. - * This way, if a register isn't actually used for anything, - * we don't retrieve it. - */ - - for (i = 0; i < ARRAY_SIZE(asc7621_params); i++) { - for (j = 0; j < ARRAY_SIZE(asc7621_params[i].msb); j++) - asc7621_register_priorities[asc7621_params[i].msb[j]] = - asc7621_params[i].priority; - for (j = 0; j < ARRAY_SIZE(asc7621_params[i].lsb); j++) - asc7621_register_priorities[asc7621_params[i].lsb[j]] = - asc7621_params[i].priority; - } - return i2c_add_driver(&asc7621_driver); -} - -static void __exit sm_asc7621_exit(void) -{ - i2c_del_driver(&asc7621_driver); -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("George Joseph"); -MODULE_DESCRIPTION("Andigilog aSC7621 and aSC7621a driver"); - -module_init(sm_asc7621_init); -module_exit(sm_asc7621_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/asus_atk0110.c b/ANDROID_3.4.5/drivers/hwmon/asus_atk0110.c deleted file mode 100644 index 351d1f45..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/asus_atk0110.c +++ /dev/null @@ -1,1463 +0,0 @@ -/* - * Copyright (C) 2007-2009 Luca Tettamanti - * - * This file is released under the GPLv2 - * See COPYING in the top level directory of the kernel tree. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -#define ATK_HID "ATK0110" - -static bool new_if; -module_param(new_if, bool, 0); -MODULE_PARM_DESC(new_if, "Override detection heuristic and force the use of the new ATK0110 interface"); - -static const struct dmi_system_id __initconst atk_force_new_if[] = { - { - /* Old interface has broken MCH temp monitoring */ - .ident = "Asus Sabertooth X58", - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58") - } - }, - { } -}; - -/* - * Minimum time between readings, enforced in order to avoid - * hogging the CPU. - */ -#define CACHE_TIME HZ - -#define BOARD_ID "MBIF" -#define METHOD_ENUMERATE "GGRP" -#define METHOD_READ "GITM" -#define METHOD_WRITE "SITM" -#define METHOD_OLD_READ_TMP "RTMP" -#define METHOD_OLD_READ_VLT "RVLT" -#define METHOD_OLD_READ_FAN "RFAN" -#define METHOD_OLD_ENUM_TMP "TSIF" -#define METHOD_OLD_ENUM_VLT "VSIF" -#define METHOD_OLD_ENUM_FAN "FSIF" - -#define ATK_MUX_HWMON 0x00000006ULL -#define ATK_MUX_MGMT 0x00000011ULL - -#define ATK_CLASS_MASK 0xff000000ULL -#define ATK_CLASS_FREQ_CTL 0x03000000ULL -#define ATK_CLASS_FAN_CTL 0x04000000ULL -#define ATK_CLASS_HWMON 0x06000000ULL -#define ATK_CLASS_MGMT 0x11000000ULL - -#define ATK_TYPE_MASK 0x00ff0000ULL -#define HWMON_TYPE_VOLT 0x00020000ULL -#define HWMON_TYPE_TEMP 0x00030000ULL -#define HWMON_TYPE_FAN 0x00040000ULL - -#define ATK_ELEMENT_ID_MASK 0x0000ffffULL - -#define ATK_EC_ID 0x11060004ULL - -enum atk_pack_member { - HWMON_PACK_FLAGS, - HWMON_PACK_NAME, - HWMON_PACK_LIMIT1, - HWMON_PACK_LIMIT2, - HWMON_PACK_ENABLE -}; - -/* New package format */ -#define _HWMON_NEW_PACK_SIZE 7 -#define _HWMON_NEW_PACK_FLAGS 0 -#define _HWMON_NEW_PACK_NAME 1 -#define _HWMON_NEW_PACK_UNK1 2 -#define _HWMON_NEW_PACK_UNK2 3 -#define _HWMON_NEW_PACK_LIMIT1 4 -#define _HWMON_NEW_PACK_LIMIT2 5 -#define _HWMON_NEW_PACK_ENABLE 6 - -/* Old package format */ -#define _HWMON_OLD_PACK_SIZE 5 -#define _HWMON_OLD_PACK_FLAGS 0 -#define _HWMON_OLD_PACK_NAME 1 -#define _HWMON_OLD_PACK_LIMIT1 2 -#define _HWMON_OLD_PACK_LIMIT2 3 -#define _HWMON_OLD_PACK_ENABLE 4 - - -struct atk_data { - struct device *hwmon_dev; - acpi_handle atk_handle; - struct acpi_device *acpi_dev; - - bool old_interface; - - /* old interface */ - acpi_handle rtmp_handle; - acpi_handle rvlt_handle; - acpi_handle rfan_handle; - /* new inteface */ - acpi_handle enumerate_handle; - acpi_handle read_handle; - acpi_handle write_handle; - - bool disable_ec; - - int voltage_count; - int temperature_count; - int fan_count; - struct list_head sensor_list; - - struct { - struct dentry *root; - u32 id; - } debugfs; -}; - - -typedef ssize_t (*sysfs_show_func)(struct device *dev, - struct device_attribute *attr, char *buf); - -static const struct acpi_device_id atk_ids[] = { - {ATK_HID, 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, atk_ids); - -#define ATTR_NAME_SIZE 16 /* Worst case is "tempN_input" */ - -struct atk_sensor_data { - struct list_head list; - struct atk_data *data; - struct device_attribute label_attr; - struct device_attribute input_attr; - struct device_attribute limit1_attr; - struct device_attribute limit2_attr; - char label_attr_name[ATTR_NAME_SIZE]; - char input_attr_name[ATTR_NAME_SIZE]; - char limit1_attr_name[ATTR_NAME_SIZE]; - char limit2_attr_name[ATTR_NAME_SIZE]; - u64 id; - u64 type; - u64 limit1; - u64 limit2; - u64 cached_value; - unsigned long last_updated; /* in jiffies */ - bool is_valid; - char const *acpi_name; -}; - -/* - * Return buffer format: - * [0-3] "value" is valid flag - * [4-7] value - * [8- ] unknown stuff on newer mobos - */ -struct atk_acpi_ret_buffer { - u32 flags; - u32 value; - u8 data[]; -}; - -/* Input buffer used for GITM and SITM methods */ -struct atk_acpi_input_buf { - u32 id; - u32 param1; - u32 param2; -}; - -static int atk_add(struct acpi_device *device); -static int atk_remove(struct acpi_device *device, int type); -static void atk_print_sensor(struct atk_data *data, union acpi_object *obj); -static int atk_read_value(struct atk_sensor_data *sensor, u64 *value); -static void atk_free_sensors(struct atk_data *data); - -static struct acpi_driver atk_driver = { - .name = ATK_HID, - .class = "hwmon", - .ids = atk_ids, - .ops = { - .add = atk_add, - .remove = atk_remove, - }, -}; - -#define input_to_atk_sensor(attr) \ - container_of(attr, struct atk_sensor_data, input_attr) - -#define label_to_atk_sensor(attr) \ - container_of(attr, struct atk_sensor_data, label_attr) - -#define limit1_to_atk_sensor(attr) \ - container_of(attr, struct atk_sensor_data, limit1_attr) - -#define limit2_to_atk_sensor(attr) \ - container_of(attr, struct atk_sensor_data, limit2_attr) - -static ssize_t atk_input_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct atk_sensor_data *s = input_to_atk_sensor(attr); - u64 value; - int err; - - err = atk_read_value(s, &value); - if (err) - return err; - - if (s->type == HWMON_TYPE_TEMP) - /* ACPI returns decidegree */ - value *= 100; - - return sprintf(buf, "%llu\n", value); -} - -static ssize_t atk_label_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct atk_sensor_data *s = label_to_atk_sensor(attr); - - return sprintf(buf, "%s\n", s->acpi_name); -} - -static ssize_t atk_limit1_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct atk_sensor_data *s = limit1_to_atk_sensor(attr); - u64 value = s->limit1; - - if (s->type == HWMON_TYPE_TEMP) - value *= 100; - - return sprintf(buf, "%lld\n", value); -} - -static ssize_t atk_limit2_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct atk_sensor_data *s = limit2_to_atk_sensor(attr); - u64 value = s->limit2; - - if (s->type == HWMON_TYPE_TEMP) - value *= 100; - - return sprintf(buf, "%lld\n", value); -} - -static ssize_t atk_name_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "atk0110\n"); -} -static struct device_attribute atk_name_attr = - __ATTR(name, 0444, atk_name_show, NULL); - -static void atk_init_attribute(struct device_attribute *attr, char *name, - sysfs_show_func show) -{ - sysfs_attr_init(&attr->attr); - attr->attr.name = name; - attr->attr.mode = 0444; - attr->show = show; - attr->store = NULL; -} - - -static union acpi_object *atk_get_pack_member(struct atk_data *data, - union acpi_object *pack, - enum atk_pack_member m) -{ - bool old_if = data->old_interface; - int offset; - - switch (m) { - case HWMON_PACK_FLAGS: - offset = old_if ? _HWMON_OLD_PACK_FLAGS : _HWMON_NEW_PACK_FLAGS; - break; - case HWMON_PACK_NAME: - offset = old_if ? _HWMON_OLD_PACK_NAME : _HWMON_NEW_PACK_NAME; - break; - case HWMON_PACK_LIMIT1: - offset = old_if ? _HWMON_OLD_PACK_LIMIT1 : - _HWMON_NEW_PACK_LIMIT1; - break; - case HWMON_PACK_LIMIT2: - offset = old_if ? _HWMON_OLD_PACK_LIMIT2 : - _HWMON_NEW_PACK_LIMIT2; - break; - case HWMON_PACK_ENABLE: - offset = old_if ? _HWMON_OLD_PACK_ENABLE : - _HWMON_NEW_PACK_ENABLE; - break; - default: - return NULL; - } - - return &pack->package.elements[offset]; -} - - -/* - * New package format is: - * - flag (int) - * class - used for de-muxing the request to the correct GITn - * type (volt, temp, fan) - * sensor id | - * sensor id - used for de-muxing the request _inside_ the GITn - * - name (str) - * - unknown (int) - * - unknown (int) - * - limit1 (int) - * - limit2 (int) - * - enable (int) - * - * The old package has the same format but it's missing the two unknown fields. - */ -static int validate_hwmon_pack(struct atk_data *data, union acpi_object *obj) -{ - struct device *dev = &data->acpi_dev->dev; - union acpi_object *tmp; - bool old_if = data->old_interface; - int const expected_size = old_if ? _HWMON_OLD_PACK_SIZE : - _HWMON_NEW_PACK_SIZE; - - if (obj->type != ACPI_TYPE_PACKAGE) { - dev_warn(dev, "Invalid type: %d\n", obj->type); - return -EINVAL; - } - - if (obj->package.count != expected_size) { - dev_warn(dev, "Invalid package size: %d, expected: %d\n", - obj->package.count, expected_size); - return -EINVAL; - } - - tmp = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS); - if (tmp->type != ACPI_TYPE_INTEGER) { - dev_warn(dev, "Invalid type (flag): %d\n", tmp->type); - return -EINVAL; - } - - tmp = atk_get_pack_member(data, obj, HWMON_PACK_NAME); - if (tmp->type != ACPI_TYPE_STRING) { - dev_warn(dev, "Invalid type (name): %d\n", tmp->type); - return -EINVAL; - } - - /* Don't check... we don't know what they're useful for anyway */ -#if 0 - tmp = &obj->package.elements[HWMON_PACK_UNK1]; - if (tmp->type != ACPI_TYPE_INTEGER) { - dev_warn(dev, "Invalid type (unk1): %d\n", tmp->type); - return -EINVAL; - } - - tmp = &obj->package.elements[HWMON_PACK_UNK2]; - if (tmp->type != ACPI_TYPE_INTEGER) { - dev_warn(dev, "Invalid type (unk2): %d\n", tmp->type); - return -EINVAL; - } -#endif - - tmp = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1); - if (tmp->type != ACPI_TYPE_INTEGER) { - dev_warn(dev, "Invalid type (limit1): %d\n", tmp->type); - return -EINVAL; - } - - tmp = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2); - if (tmp->type != ACPI_TYPE_INTEGER) { - dev_warn(dev, "Invalid type (limit2): %d\n", tmp->type); - return -EINVAL; - } - - tmp = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE); - if (tmp->type != ACPI_TYPE_INTEGER) { - dev_warn(dev, "Invalid type (enable): %d\n", tmp->type); - return -EINVAL; - } - - atk_print_sensor(data, obj); - - return 0; -} - -#ifdef DEBUG -static char const *atk_sensor_type(union acpi_object *flags) -{ - u64 type = flags->integer.value & ATK_TYPE_MASK; - char const *what; - - switch (type) { - case HWMON_TYPE_VOLT: - what = "voltage"; - break; - case HWMON_TYPE_TEMP: - what = "temperature"; - break; - case HWMON_TYPE_FAN: - what = "fan"; - break; - default: - what = "unknown"; - break; - } - - return what; -} -#endif - -static void atk_print_sensor(struct atk_data *data, union acpi_object *obj) -{ -#ifdef DEBUG - struct device *dev = &data->acpi_dev->dev; - union acpi_object *flags; - union acpi_object *name; - union acpi_object *limit1; - union acpi_object *limit2; - union acpi_object *enable; - char const *what; - - flags = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS); - name = atk_get_pack_member(data, obj, HWMON_PACK_NAME); - limit1 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1); - limit2 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2); - enable = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE); - - what = atk_sensor_type(flags); - - dev_dbg(dev, "%s: %#llx %s [%llu-%llu] %s\n", what, - flags->integer.value, - name->string.pointer, - limit1->integer.value, limit2->integer.value, - enable->integer.value ? "enabled" : "disabled"); -#endif -} - -static int atk_read_value_old(struct atk_sensor_data *sensor, u64 *value) -{ - struct atk_data *data = sensor->data; - struct device *dev = &data->acpi_dev->dev; - struct acpi_object_list params; - union acpi_object id; - acpi_status status; - acpi_handle method; - - switch (sensor->type) { - case HWMON_TYPE_VOLT: - method = data->rvlt_handle; - break; - case HWMON_TYPE_TEMP: - method = data->rtmp_handle; - break; - case HWMON_TYPE_FAN: - method = data->rfan_handle; - break; - default: - return -EINVAL; - } - - id.type = ACPI_TYPE_INTEGER; - id.integer.value = sensor->id; - - params.count = 1; - params.pointer = &id; - - status = acpi_evaluate_integer(method, NULL, ¶ms, value); - if (status != AE_OK) { - dev_warn(dev, "%s: ACPI exception: %s\n", __func__, - acpi_format_exception(status)); - return -EIO; - } - - return 0; -} - -static union acpi_object *atk_ggrp(struct atk_data *data, u16 mux) -{ - struct device *dev = &data->acpi_dev->dev; - struct acpi_buffer buf; - acpi_status ret; - struct acpi_object_list params; - union acpi_object id; - union acpi_object *pack; - - id.type = ACPI_TYPE_INTEGER; - id.integer.value = mux; - params.count = 1; - params.pointer = &id; - - buf.length = ACPI_ALLOCATE_BUFFER; - ret = acpi_evaluate_object(data->enumerate_handle, NULL, ¶ms, &buf); - if (ret != AE_OK) { - dev_err(dev, "GGRP[%#x] ACPI exception: %s\n", mux, - acpi_format_exception(ret)); - return ERR_PTR(-EIO); - } - pack = buf.pointer; - if (pack->type != ACPI_TYPE_PACKAGE) { - /* Execution was successful, but the id was not found */ - ACPI_FREE(pack); - return ERR_PTR(-ENOENT); - } - - if (pack->package.count < 1) { - dev_err(dev, "GGRP[%#x] package is too small\n", mux); - ACPI_FREE(pack); - return ERR_PTR(-EIO); - } - return pack; -} - -static union acpi_object *atk_gitm(struct atk_data *data, u64 id) -{ - struct device *dev = &data->acpi_dev->dev; - struct atk_acpi_input_buf buf; - union acpi_object tmp; - struct acpi_object_list params; - struct acpi_buffer ret; - union acpi_object *obj; - acpi_status status; - - buf.id = id; - buf.param1 = 0; - buf.param2 = 0; - - tmp.type = ACPI_TYPE_BUFFER; - tmp.buffer.pointer = (u8 *)&buf; - tmp.buffer.length = sizeof(buf); - - params.count = 1; - params.pointer = (void *)&tmp; - - ret.length = ACPI_ALLOCATE_BUFFER; - status = acpi_evaluate_object_typed(data->read_handle, NULL, ¶ms, - &ret, ACPI_TYPE_BUFFER); - if (status != AE_OK) { - dev_warn(dev, "GITM[%#llx] ACPI exception: %s\n", id, - acpi_format_exception(status)); - return ERR_PTR(-EIO); - } - obj = ret.pointer; - - /* Sanity check */ - if (obj->buffer.length < 8) { - dev_warn(dev, "Unexpected ASBF length: %u\n", - obj->buffer.length); - ACPI_FREE(obj); - return ERR_PTR(-EIO); - } - return obj; -} - -static union acpi_object *atk_sitm(struct atk_data *data, - struct atk_acpi_input_buf *buf) -{ - struct device *dev = &data->acpi_dev->dev; - struct acpi_object_list params; - union acpi_object tmp; - struct acpi_buffer ret; - union acpi_object *obj; - acpi_status status; - - tmp.type = ACPI_TYPE_BUFFER; - tmp.buffer.pointer = (u8 *)buf; - tmp.buffer.length = sizeof(*buf); - - params.count = 1; - params.pointer = &tmp; - - ret.length = ACPI_ALLOCATE_BUFFER; - status = acpi_evaluate_object_typed(data->write_handle, NULL, ¶ms, - &ret, ACPI_TYPE_BUFFER); - if (status != AE_OK) { - dev_warn(dev, "SITM[%#x] ACPI exception: %s\n", buf->id, - acpi_format_exception(status)); - return ERR_PTR(-EIO); - } - obj = ret.pointer; - - /* Sanity check */ - if (obj->buffer.length < 8) { - dev_warn(dev, "Unexpected ASBF length: %u\n", - obj->buffer.length); - ACPI_FREE(obj); - return ERR_PTR(-EIO); - } - return obj; -} - -static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) -{ - struct atk_data *data = sensor->data; - struct device *dev = &data->acpi_dev->dev; - union acpi_object *obj; - struct atk_acpi_ret_buffer *buf; - int err = 0; - - obj = atk_gitm(data, sensor->id); - if (IS_ERR(obj)) - return PTR_ERR(obj); - - buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; - if (buf->flags == 0) { - /* - * The reading is not valid, possible causes: - * - sensor failure - * - enumeration was FUBAR (and we didn't notice) - */ - dev_warn(dev, "Read failed, sensor = %#llx\n", sensor->id); - err = -EIO; - goto out; - } - - *value = buf->value; -out: - ACPI_FREE(obj); - return err; -} - -static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) -{ - int err; - - if (!sensor->is_valid || - time_after(jiffies, sensor->last_updated + CACHE_TIME)) { - if (sensor->data->old_interface) - err = atk_read_value_old(sensor, value); - else - err = atk_read_value_new(sensor, value); - - sensor->is_valid = true; - sensor->last_updated = jiffies; - sensor->cached_value = *value; - } else { - *value = sensor->cached_value; - err = 0; - } - - return err; -} - -#ifdef CONFIG_DEBUG_FS -static int atk_debugfs_gitm_get(void *p, u64 *val) -{ - struct atk_data *data = p; - union acpi_object *ret; - struct atk_acpi_ret_buffer *buf; - int err = 0; - - if (!data->read_handle) - return -ENODEV; - - if (!data->debugfs.id) - return -EINVAL; - - ret = atk_gitm(data, data->debugfs.id); - if (IS_ERR(ret)) - return PTR_ERR(ret); - - buf = (struct atk_acpi_ret_buffer *)ret->buffer.pointer; - if (buf->flags) - *val = buf->value; - else - err = -EIO; - - ACPI_FREE(ret); - return err; -} - -DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm, - atk_debugfs_gitm_get, - NULL, - "0x%08llx\n") - -static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj) -{ - int ret = 0; - - switch (obj->type) { - case ACPI_TYPE_INTEGER: - ret = snprintf(buf, sz, "0x%08llx\n", obj->integer.value); - break; - case ACPI_TYPE_STRING: - ret = snprintf(buf, sz, "%s\n", obj->string.pointer); - break; - } - - return ret; -} - -static void atk_pack_print(char *buf, size_t sz, union acpi_object *pack) -{ - int ret; - int i; - - for (i = 0; i < pack->package.count; i++) { - union acpi_object *obj = &pack->package.elements[i]; - - ret = atk_acpi_print(buf, sz, obj); - if (ret >= sz) - break; - buf += ret; - sz -= ret; - } -} - -static int atk_debugfs_ggrp_open(struct inode *inode, struct file *file) -{ - struct atk_data *data = inode->i_private; - char *buf = NULL; - union acpi_object *ret; - u8 cls; - int i; - - if (!data->enumerate_handle) - return -ENODEV; - if (!data->debugfs.id) - return -EINVAL; - - cls = (data->debugfs.id & 0xff000000) >> 24; - ret = atk_ggrp(data, cls); - if (IS_ERR(ret)) - return PTR_ERR(ret); - - for (i = 0; i < ret->package.count; i++) { - union acpi_object *pack = &ret->package.elements[i]; - union acpi_object *id; - - if (pack->type != ACPI_TYPE_PACKAGE) - continue; - if (!pack->package.count) - continue; - id = &pack->package.elements[0]; - if (id->integer.value == data->debugfs.id) { - /* Print the package */ - buf = kzalloc(512, GFP_KERNEL); - if (!buf) { - ACPI_FREE(ret); - return -ENOMEM; - } - atk_pack_print(buf, 512, pack); - break; - } - } - ACPI_FREE(ret); - - if (!buf) - return -EINVAL; - - file->private_data = buf; - - return nonseekable_open(inode, file); -} - -static ssize_t atk_debugfs_ggrp_read(struct file *file, char __user *buf, - size_t count, loff_t *pos) -{ - char *str = file->private_data; - size_t len = strlen(str); - - return simple_read_from_buffer(buf, count, pos, str, len); -} - -static int atk_debugfs_ggrp_release(struct inode *inode, struct file *file) -{ - kfree(file->private_data); - return 0; -} - -static const struct file_operations atk_debugfs_ggrp_fops = { - .read = atk_debugfs_ggrp_read, - .open = atk_debugfs_ggrp_open, - .release = atk_debugfs_ggrp_release, - .llseek = no_llseek, -}; - -static void atk_debugfs_init(struct atk_data *data) -{ - struct dentry *d; - struct dentry *f; - - data->debugfs.id = 0; - - d = debugfs_create_dir("asus_atk0110", NULL); - if (!d || IS_ERR(d)) - return; - - f = debugfs_create_x32("id", S_IRUSR | S_IWUSR, d, &data->debugfs.id); - if (!f || IS_ERR(f)) - goto cleanup; - - f = debugfs_create_file("gitm", S_IRUSR, d, data, - &atk_debugfs_gitm); - if (!f || IS_ERR(f)) - goto cleanup; - - f = debugfs_create_file("ggrp", S_IRUSR, d, data, - &atk_debugfs_ggrp_fops); - if (!f || IS_ERR(f)) - goto cleanup; - - data->debugfs.root = d; - - return; -cleanup: - debugfs_remove_recursive(d); -} - -static void atk_debugfs_cleanup(struct atk_data *data) -{ - debugfs_remove_recursive(data->debugfs.root); -} - -#else /* CONFIG_DEBUG_FS */ - -static void atk_debugfs_init(struct atk_data *data) -{ -} - -static void atk_debugfs_cleanup(struct atk_data *data) -{ -} -#endif - -static int atk_add_sensor(struct atk_data *data, union acpi_object *obj) -{ - struct device *dev = &data->acpi_dev->dev; - union acpi_object *flags; - union acpi_object *name; - union acpi_object *limit1; - union acpi_object *limit2; - union acpi_object *enable; - struct atk_sensor_data *sensor; - char const *base_name; - char const *limit1_name; - char const *limit2_name; - u64 type; - int err; - int *num; - int start; - - if (obj->type != ACPI_TYPE_PACKAGE) { - /* wft is this? */ - dev_warn(dev, "Unknown type for ACPI object: (%d)\n", - obj->type); - return -EINVAL; - } - - err = validate_hwmon_pack(data, obj); - if (err) - return err; - - /* Ok, we have a valid hwmon package */ - type = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS)->integer.value - & ATK_TYPE_MASK; - - switch (type) { - case HWMON_TYPE_VOLT: - base_name = "in"; - limit1_name = "min"; - limit2_name = "max"; - num = &data->voltage_count; - start = 0; - break; - case HWMON_TYPE_TEMP: - base_name = "temp"; - limit1_name = "max"; - limit2_name = "crit"; - num = &data->temperature_count; - start = 1; - break; - case HWMON_TYPE_FAN: - base_name = "fan"; - limit1_name = "min"; - limit2_name = "max"; - num = &data->fan_count; - start = 1; - break; - default: - dev_warn(dev, "Unknown sensor type: %#llx\n", type); - return -EINVAL; - } - - enable = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE); - if (!enable->integer.value) - /* sensor is disabled */ - return 0; - - flags = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS); - name = atk_get_pack_member(data, obj, HWMON_PACK_NAME); - limit1 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1); - limit2 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2); - - sensor = kzalloc(sizeof(*sensor), GFP_KERNEL); - if (!sensor) - return -ENOMEM; - - sensor->acpi_name = kstrdup(name->string.pointer, GFP_KERNEL); - if (!sensor->acpi_name) { - err = -ENOMEM; - goto out; - } - - INIT_LIST_HEAD(&sensor->list); - sensor->type = type; - sensor->data = data; - sensor->id = flags->integer.value; - sensor->limit1 = limit1->integer.value; - if (data->old_interface) - sensor->limit2 = limit2->integer.value; - else - /* The upper limit is expressed as delta from lower limit */ - sensor->limit2 = sensor->limit1 + limit2->integer.value; - - snprintf(sensor->input_attr_name, ATTR_NAME_SIZE, - "%s%d_input", base_name, start + *num); - atk_init_attribute(&sensor->input_attr, - sensor->input_attr_name, - atk_input_show); - - snprintf(sensor->label_attr_name, ATTR_NAME_SIZE, - "%s%d_label", base_name, start + *num); - atk_init_attribute(&sensor->label_attr, - sensor->label_attr_name, - atk_label_show); - - snprintf(sensor->limit1_attr_name, ATTR_NAME_SIZE, - "%s%d_%s", base_name, start + *num, limit1_name); - atk_init_attribute(&sensor->limit1_attr, - sensor->limit1_attr_name, - atk_limit1_show); - - snprintf(sensor->limit2_attr_name, ATTR_NAME_SIZE, - "%s%d_%s", base_name, start + *num, limit2_name); - atk_init_attribute(&sensor->limit2_attr, - sensor->limit2_attr_name, - atk_limit2_show); - - list_add(&sensor->list, &data->sensor_list); - (*num)++; - - return 1; -out: - kfree(sensor->acpi_name); - kfree(sensor); - return err; -} - -static int atk_enumerate_old_hwmon(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - struct acpi_buffer buf; - union acpi_object *pack; - acpi_status status; - int i, ret; - int count = 0; - - /* Voltages */ - buf.length = ACPI_ALLOCATE_BUFFER; - status = acpi_evaluate_object_typed(data->atk_handle, - METHOD_OLD_ENUM_VLT, NULL, &buf, ACPI_TYPE_PACKAGE); - if (status != AE_OK) { - dev_warn(dev, METHOD_OLD_ENUM_VLT ": ACPI exception: %s\n", - acpi_format_exception(status)); - - return -ENODEV; - } - - pack = buf.pointer; - for (i = 1; i < pack->package.count; i++) { - union acpi_object *obj = &pack->package.elements[i]; - - ret = atk_add_sensor(data, obj); - if (ret > 0) - count++; - } - ACPI_FREE(buf.pointer); - - /* Temperatures */ - buf.length = ACPI_ALLOCATE_BUFFER; - status = acpi_evaluate_object_typed(data->atk_handle, - METHOD_OLD_ENUM_TMP, NULL, &buf, ACPI_TYPE_PACKAGE); - if (status != AE_OK) { - dev_warn(dev, METHOD_OLD_ENUM_TMP ": ACPI exception: %s\n", - acpi_format_exception(status)); - - ret = -ENODEV; - goto cleanup; - } - - pack = buf.pointer; - for (i = 1; i < pack->package.count; i++) { - union acpi_object *obj = &pack->package.elements[i]; - - ret = atk_add_sensor(data, obj); - if (ret > 0) - count++; - } - ACPI_FREE(buf.pointer); - - /* Fans */ - buf.length = ACPI_ALLOCATE_BUFFER; - status = acpi_evaluate_object_typed(data->atk_handle, - METHOD_OLD_ENUM_FAN, NULL, &buf, ACPI_TYPE_PACKAGE); - if (status != AE_OK) { - dev_warn(dev, METHOD_OLD_ENUM_FAN ": ACPI exception: %s\n", - acpi_format_exception(status)); - - ret = -ENODEV; - goto cleanup; - } - - pack = buf.pointer; - for (i = 1; i < pack->package.count; i++) { - union acpi_object *obj = &pack->package.elements[i]; - - ret = atk_add_sensor(data, obj); - if (ret > 0) - count++; - } - ACPI_FREE(buf.pointer); - - return count; -cleanup: - atk_free_sensors(data); - return ret; -} - -static int atk_ec_present(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - union acpi_object *pack; - union acpi_object *ec; - int ret; - int i; - - pack = atk_ggrp(data, ATK_MUX_MGMT); - if (IS_ERR(pack)) { - if (PTR_ERR(pack) == -ENOENT) { - /* The MGMT class does not exists - that's ok */ - dev_dbg(dev, "Class %#llx not found\n", ATK_MUX_MGMT); - return 0; - } - return PTR_ERR(pack); - } - - /* Search the EC */ - ec = NULL; - for (i = 0; i < pack->package.count; i++) { - union acpi_object *obj = &pack->package.elements[i]; - union acpi_object *id; - - if (obj->type != ACPI_TYPE_PACKAGE) - continue; - - id = &obj->package.elements[0]; - if (id->type != ACPI_TYPE_INTEGER) - continue; - - if (id->integer.value == ATK_EC_ID) { - ec = obj; - break; - } - } - - ret = (ec != NULL); - if (!ret) - /* The system has no EC */ - dev_dbg(dev, "EC not found\n"); - - ACPI_FREE(pack); - return ret; -} - -static int atk_ec_enabled(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - union acpi_object *obj; - struct atk_acpi_ret_buffer *buf; - int err; - - obj = atk_gitm(data, ATK_EC_ID); - if (IS_ERR(obj)) { - dev_err(dev, "Unable to query EC status\n"); - return PTR_ERR(obj); - } - buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; - - if (buf->flags == 0) { - dev_err(dev, "Unable to query EC status\n"); - err = -EIO; - } else { - err = (buf->value != 0); - dev_dbg(dev, "EC is %sabled\n", - err ? "en" : "dis"); - } - - ACPI_FREE(obj); - return err; -} - -static int atk_ec_ctl(struct atk_data *data, int enable) -{ - struct device *dev = &data->acpi_dev->dev; - union acpi_object *obj; - struct atk_acpi_input_buf sitm; - struct atk_acpi_ret_buffer *ec_ret; - int err = 0; - - sitm.id = ATK_EC_ID; - sitm.param1 = enable; - sitm.param2 = 0; - - obj = atk_sitm(data, &sitm); - if (IS_ERR(obj)) { - dev_err(dev, "Failed to %sable the EC\n", - enable ? "en" : "dis"); - return PTR_ERR(obj); - } - ec_ret = (struct atk_acpi_ret_buffer *)obj->buffer.pointer; - if (ec_ret->flags == 0) { - dev_err(dev, "Failed to %sable the EC\n", - enable ? "en" : "dis"); - err = -EIO; - } else { - dev_info(dev, "EC %sabled\n", - enable ? "en" : "dis"); - } - - ACPI_FREE(obj); - return err; -} - -static int atk_enumerate_new_hwmon(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - union acpi_object *pack; - int err; - int i; - - err = atk_ec_present(data); - if (err < 0) - return err; - if (err) { - err = atk_ec_enabled(data); - if (err < 0) - return err; - /* If the EC was disabled we will disable it again on unload */ - data->disable_ec = err; - - err = atk_ec_ctl(data, 1); - if (err) { - data->disable_ec = false; - return err; - } - } - - dev_dbg(dev, "Enumerating hwmon sensors\n"); - - pack = atk_ggrp(data, ATK_MUX_HWMON); - if (IS_ERR(pack)) - return PTR_ERR(pack); - - for (i = 0; i < pack->package.count; i++) { - union acpi_object *obj = &pack->package.elements[i]; - - atk_add_sensor(data, obj); - } - - err = data->voltage_count + data->temperature_count + data->fan_count; - - ACPI_FREE(pack); - return err; -} - -static int atk_create_files(struct atk_data *data) -{ - struct atk_sensor_data *s; - int err; - - list_for_each_entry(s, &data->sensor_list, list) { - err = device_create_file(data->hwmon_dev, &s->input_attr); - if (err) - return err; - err = device_create_file(data->hwmon_dev, &s->label_attr); - if (err) - return err; - err = device_create_file(data->hwmon_dev, &s->limit1_attr); - if (err) - return err; - err = device_create_file(data->hwmon_dev, &s->limit2_attr); - if (err) - return err; - } - - err = device_create_file(data->hwmon_dev, &atk_name_attr); - - return err; -} - -static void atk_remove_files(struct atk_data *data) -{ - struct atk_sensor_data *s; - - list_for_each_entry(s, &data->sensor_list, list) { - device_remove_file(data->hwmon_dev, &s->input_attr); - device_remove_file(data->hwmon_dev, &s->label_attr); - device_remove_file(data->hwmon_dev, &s->limit1_attr); - device_remove_file(data->hwmon_dev, &s->limit2_attr); - } - device_remove_file(data->hwmon_dev, &atk_name_attr); -} - -static void atk_free_sensors(struct atk_data *data) -{ - struct list_head *head = &data->sensor_list; - struct atk_sensor_data *s, *tmp; - - list_for_each_entry_safe(s, tmp, head, list) { - kfree(s->acpi_name); - kfree(s); - } -} - -static int atk_register_hwmon(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - int err; - - dev_dbg(dev, "registering hwmon device\n"); - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) - return PTR_ERR(data->hwmon_dev); - - dev_dbg(dev, "populating sysfs directory\n"); - err = atk_create_files(data); - if (err) - goto remove; - - return 0; -remove: - /* Cleanup the registered files */ - atk_remove_files(data); - hwmon_device_unregister(data->hwmon_dev); - return err; -} - -static int atk_probe_if(struct atk_data *data) -{ - struct device *dev = &data->acpi_dev->dev; - acpi_handle ret; - acpi_status status; - int err = 0; - - /* RTMP: read temperature */ - status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret); - if (ACPI_SUCCESS(status)) - data->rtmp_handle = ret; - else - dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n", - acpi_format_exception(status)); - - /* RVLT: read voltage */ - status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret); - if (ACPI_SUCCESS(status)) - data->rvlt_handle = ret; - else - dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n", - acpi_format_exception(status)); - - /* RFAN: read fan status */ - status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret); - if (ACPI_SUCCESS(status)) - data->rfan_handle = ret; - else - dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n", - acpi_format_exception(status)); - - /* Enumeration */ - status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret); - if (ACPI_SUCCESS(status)) - data->enumerate_handle = ret; - else - dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n", - acpi_format_exception(status)); - - /* De-multiplexer (read) */ - status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret); - if (ACPI_SUCCESS(status)) - data->read_handle = ret; - else - dev_dbg(dev, "method " METHOD_READ " not found: %s\n", - acpi_format_exception(status)); - - /* De-multiplexer (write) */ - status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret); - if (ACPI_SUCCESS(status)) - data->write_handle = ret; - else - dev_dbg(dev, "method " METHOD_WRITE " not found: %s\n", - acpi_format_exception(status)); - - /* - * Check for hwmon methods: first check "old" style methods; note that - * both may be present: in this case we stick to the old interface; - * analysis of multiple DSDTs indicates that when both interfaces - * are present the new one (GGRP/GITM) is not functional. - */ - if (new_if) - dev_info(dev, "Overriding interface detection\n"); - if (data->rtmp_handle && - data->rvlt_handle && data->rfan_handle && !new_if) - data->old_interface = true; - else if (data->enumerate_handle && data->read_handle && - data->write_handle) - data->old_interface = false; - else - err = -ENODEV; - - return err; -} - -static int atk_add(struct acpi_device *device) -{ - acpi_status ret; - int err; - struct acpi_buffer buf; - union acpi_object *obj; - struct atk_data *data; - - dev_dbg(&device->dev, "adding...\n"); - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->acpi_dev = device; - data->atk_handle = device->handle; - INIT_LIST_HEAD(&data->sensor_list); - data->disable_ec = false; - - buf.length = ACPI_ALLOCATE_BUFFER; - ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL, - &buf, ACPI_TYPE_PACKAGE); - if (ret != AE_OK) { - dev_dbg(&device->dev, "atk: method MBIF not found\n"); - } else { - obj = buf.pointer; - if (obj->package.count >= 2) { - union acpi_object *id = &obj->package.elements[1]; - if (id->type == ACPI_TYPE_STRING) - dev_dbg(&device->dev, "board ID = %s\n", - id->string.pointer); - } - ACPI_FREE(buf.pointer); - } - - err = atk_probe_if(data); - if (err) { - dev_err(&device->dev, "No usable hwmon interface detected\n"); - goto out; - } - - if (data->old_interface) { - dev_dbg(&device->dev, "Using old hwmon interface\n"); - err = atk_enumerate_old_hwmon(data); - } else { - dev_dbg(&device->dev, "Using new hwmon interface\n"); - err = atk_enumerate_new_hwmon(data); - } - if (err < 0) - goto out; - if (err == 0) { - dev_info(&device->dev, - "No usable sensor detected, bailing out\n"); - err = -ENODEV; - goto out; - } - - err = atk_register_hwmon(data); - if (err) - goto cleanup; - - atk_debugfs_init(data); - - device->driver_data = data; - return 0; -cleanup: - atk_free_sensors(data); -out: - if (data->disable_ec) - atk_ec_ctl(data, 0); - kfree(data); - return err; -} - -static int atk_remove(struct acpi_device *device, int type) -{ - struct atk_data *data = device->driver_data; - dev_dbg(&device->dev, "removing...\n"); - - device->driver_data = NULL; - - atk_debugfs_cleanup(data); - - atk_remove_files(data); - atk_free_sensors(data); - hwmon_device_unregister(data->hwmon_dev); - - if (data->disable_ec) { - if (atk_ec_ctl(data, 0)) - dev_err(&device->dev, "Failed to disable EC\n"); - } - - kfree(data); - - return 0; -} - -static int __init atk0110_init(void) -{ - int ret; - - /* Make sure it's safe to access the device through ACPI */ - if (!acpi_resources_are_enforced()) { - pr_err("Resources not safely usable due to acpi_enforce_resources kernel parameter\n"); - return -EBUSY; - } - - if (dmi_check_system(atk_force_new_if)) - new_if = true; - - ret = acpi_bus_register_driver(&atk_driver); - if (ret) - pr_info("acpi_bus_register_driver failed: %d\n", ret); - - return ret; -} - -static void __exit atk0110_exit(void) -{ - acpi_bus_unregister_driver(&atk_driver); -} - -module_init(atk0110_init); -module_exit(atk0110_exit); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/atxp1.c b/ANDROID_3.4.5/drivers/hwmon/atxp1.c deleted file mode 100644 index 58af6aa9..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/atxp1.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * atxp1.c - kernel module for setting CPU VID and general purpose - * I/Os using the Attansic ATXP1 chip. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("System voltages control via Attansic ATXP1"); -MODULE_VERSION("0.6.3"); -MODULE_AUTHOR("Sebastian Witt "); - -#define ATXP1_VID 0x00 -#define ATXP1_CVID 0x01 -#define ATXP1_GPIO1 0x06 -#define ATXP1_GPIO2 0x0a -#define ATXP1_VIDENA 0x20 -#define ATXP1_VIDMASK 0x1f -#define ATXP1_GPIO1MASK 0x0f - -static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; - -static int atxp1_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int atxp1_remove(struct i2c_client *client); -static struct atxp1_data *atxp1_update_device(struct device *dev); -static int atxp1_detect(struct i2c_client *client, struct i2c_board_info *info); - -static const struct i2c_device_id atxp1_id[] = { - { "atxp1", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, atxp1_id); - -static struct i2c_driver atxp1_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "atxp1", - }, - .probe = atxp1_probe, - .remove = atxp1_remove, - .id_table = atxp1_id, - .detect = atxp1_detect, - .address_list = normal_i2c, -}; - -struct atxp1_data { - struct device *hwmon_dev; - struct mutex update_lock; - unsigned long last_updated; - u8 valid; - struct { - u8 vid; /* VID output register */ - u8 cpu_vid; /* VID input from CPU */ - u8 gpio1; /* General purpose I/O register 1 */ - u8 gpio2; /* General purpose I/O register 2 */ - } reg; - u8 vrm; /* Detected CPU VRM */ -}; - -static struct atxp1_data *atxp1_update_device(struct device *dev) -{ - struct i2c_client *client; - struct atxp1_data *data; - - client = to_i2c_client(dev); - data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - - /* Update local register data */ - data->reg.vid = i2c_smbus_read_byte_data(client, ATXP1_VID); - data->reg.cpu_vid = i2c_smbus_read_byte_data(client, - ATXP1_CVID); - data->reg.gpio1 = i2c_smbus_read_byte_data(client, ATXP1_GPIO1); - data->reg.gpio2 = i2c_smbus_read_byte_data(client, ATXP1_GPIO2); - - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* sys file functions for cpu0_vid */ -static ssize_t atxp1_showvcore(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int size; - struct atxp1_data *data; - - data = atxp1_update_device(dev); - - size = sprintf(buf, "%d\n", vid_from_reg(data->reg.vid & ATXP1_VIDMASK, - data->vrm)); - - return size; -} - -static ssize_t atxp1_storevcore(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct atxp1_data *data; - struct i2c_client *client; - int vid, cvid; - unsigned long vcore; - int err; - - client = to_i2c_client(dev); - data = atxp1_update_device(dev); - - err = kstrtoul(buf, 10, &vcore); - if (err) - return err; - - vcore /= 25; - vcore *= 25; - - /* Calculate VID */ - vid = vid_to_reg(vcore, data->vrm); - - if (vid < 0) { - dev_err(dev, "VID calculation failed.\n"); - return -1; - } - - /* - * If output enabled, use control register value. - * Otherwise original CPU VID - */ - if (data->reg.vid & ATXP1_VIDENA) - cvid = data->reg.vid & ATXP1_VIDMASK; - else - cvid = data->reg.cpu_vid; - - /* Nothing changed, aborting */ - if (vid == cvid) - return count; - - dev_dbg(dev, "Setting VCore to %d mV (0x%02x)\n", (int)vcore, vid); - - /* Write every 25 mV step to increase stability */ - if (cvid > vid) { - for (; cvid >= vid; cvid--) - i2c_smbus_write_byte_data(client, - ATXP1_VID, cvid | ATXP1_VIDENA); - } else { - for (; cvid <= vid; cvid++) - i2c_smbus_write_byte_data(client, - ATXP1_VID, cvid | ATXP1_VIDENA); - } - - data->valid = 0; - - return count; -} - -/* - * CPU core reference voltage - * unit: millivolt - */ -static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, - atxp1_storevcore); - -/* sys file functions for GPIO1 */ -static ssize_t atxp1_showgpio1(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int size; - struct atxp1_data *data; - - data = atxp1_update_device(dev); - - size = sprintf(buf, "0x%02x\n", data->reg.gpio1 & ATXP1_GPIO1MASK); - - return size; -} - -static ssize_t atxp1_storegpio1(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct atxp1_data *data; - struct i2c_client *client; - unsigned long value; - int err; - - client = to_i2c_client(dev); - data = atxp1_update_device(dev); - - err = kstrtoul(buf, 16, &value); - if (err) - return err; - - value &= ATXP1_GPIO1MASK; - - if (value != (data->reg.gpio1 & ATXP1_GPIO1MASK)) { - dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value); - - i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value); - - data->valid = 0; - } - - return count; -} - -/* - * GPIO1 data register - * unit: Four bit as hex (e.g. 0x0f) - */ -static DEVICE_ATTR(gpio1, S_IRUGO | S_IWUSR, atxp1_showgpio1, atxp1_storegpio1); - -/* sys file functions for GPIO2 */ -static ssize_t atxp1_showgpio2(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int size; - struct atxp1_data *data; - - data = atxp1_update_device(dev); - - size = sprintf(buf, "0x%02x\n", data->reg.gpio2); - - return size; -} - -static ssize_t atxp1_storegpio2(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct atxp1_data *data = atxp1_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); - unsigned long value; - int err; - - err = kstrtoul(buf, 16, &value); - if (err) - return err; - value &= 0xff; - - if (value != data->reg.gpio2) { - dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value); - - i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value); - - data->valid = 0; - } - - return count; -} - -/* - * GPIO2 data register - * unit: Eight bit as hex (e.g. 0xff) - */ -static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); - -static struct attribute *atxp1_attributes[] = { - &dev_attr_gpio1.attr, - &dev_attr_gpio2.attr, - &dev_attr_cpu0_vid.attr, - NULL -}; - -static const struct attribute_group atxp1_group = { - .attrs = atxp1_attributes, -}; - - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int atxp1_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - - u8 temp; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Detect ATXP1, checking if vendor ID registers are all zero */ - if (!((i2c_smbus_read_byte_data(new_client, 0x3e) == 0) && - (i2c_smbus_read_byte_data(new_client, 0x3f) == 0) && - (i2c_smbus_read_byte_data(new_client, 0xfe) == 0) && - (i2c_smbus_read_byte_data(new_client, 0xff) == 0))) - return -ENODEV; - - /* - * No vendor ID, now checking if registers 0x10,0x11 (non-existent) - * showing the same as register 0x00 - */ - temp = i2c_smbus_read_byte_data(new_client, 0x00); - - if (!((i2c_smbus_read_byte_data(new_client, 0x10) == temp) && - (i2c_smbus_read_byte_data(new_client, 0x11) == temp))) - return -ENODEV; - - /* Get VRM */ - temp = vid_which_vrm(); - - if ((temp != 90) && (temp != 91)) { - dev_err(&adapter->dev, "atxp1: Not supporting VRM %d.%d\n", - temp / 10, temp % 10); - return -ENODEV; - } - - strlcpy(info->type, "atxp1", I2C_NAME_SIZE); - - return 0; -} - -static int atxp1_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct atxp1_data *data; - int err; - - data = kzalloc(sizeof(struct atxp1_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - /* Get VRM */ - data->vrm = vid_which_vrm(); - - i2c_set_clientdata(new_client, data); - data->valid = 0; - - mutex_init(&data->update_lock); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - dev_info(&new_client->dev, "Using VRM: %d.%d\n", - data->vrm / 10, data->vrm % 10); - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &atxp1_group); -exit_free: - kfree(data); -exit: - return err; -}; - -static int atxp1_remove(struct i2c_client *client) -{ - struct atxp1_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &atxp1_group); - - kfree(data); - - return 0; -}; - -module_i2c_driver(atxp1_driver); diff --git a/ANDROID_3.4.5/drivers/hwmon/coretemp.c b/ANDROID_3.4.5/drivers/hwmon/coretemp.c deleted file mode 100644 index 0f527999..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/coretemp.c +++ /dev/null @@ -1,830 +0,0 @@ -/* - * coretemp.c - Linux kernel module for hardware monitoring - * - * Copyright (C) 2007 Rudolf Marek - * - * Inspired from many hwmon drivers - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "coretemp" - -/* - * force_tjmax only matters when TjMax can't be read from the CPU itself. - * When set, it replaces the driver's suboptimal heuristic. - */ -static int force_tjmax; -module_param_named(tjmax, force_tjmax, int, 0444); -MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius"); - -#define BASE_SYSFS_ATTR_NO 2 /* Sysfs Base attr no for coretemp */ -#define NUM_REAL_CORES 32 /* Number of Real cores per cpu */ -#define CORETEMP_NAME_LENGTH 17 /* String Length of attrs */ -#define MAX_CORE_ATTRS 4 /* Maximum no of basic attrs */ -#define TOTAL_ATTRS (MAX_CORE_ATTRS + 1) -#define MAX_CORE_DATA (NUM_REAL_CORES + BASE_SYSFS_ATTR_NO) - -#define TO_PHYS_ID(cpu) (cpu_data(cpu).phys_proc_id) -#define TO_CORE_ID(cpu) (cpu_data(cpu).cpu_core_id) -#define TO_ATTR_NO(cpu) (TO_CORE_ID(cpu) + BASE_SYSFS_ATTR_NO) - -#ifdef CONFIG_SMP -#define for_each_sibling(i, cpu) for_each_cpu(i, cpu_sibling_mask(cpu)) -#else -#define for_each_sibling(i, cpu) for (i = 0; false; ) -#endif - -/* - * Per-Core Temperature Data - * @last_updated: The time when the current temperature value was updated - * earlier (in jiffies). - * @cpu_core_id: The CPU Core from which temperature values should be read - * This value is passed as "id" field to rdmsr/wrmsr functions. - * @status_reg: One of IA32_THERM_STATUS or IA32_PACKAGE_THERM_STATUS, - * from where the temperature values should be read. - * @attr_size: Total number of pre-core attrs displayed in the sysfs. - * @is_pkg_data: If this is 1, the temp_data holds pkgtemp data. - * Otherwise, temp_data holds coretemp data. - * @valid: If this is 1, the current temperature is valid. - */ -struct temp_data { - int temp; - int ttarget; - int tjmax; - unsigned long last_updated; - unsigned int cpu; - u32 cpu_core_id; - u32 status_reg; - int attr_size; - bool is_pkg_data; - bool valid; - struct sensor_device_attribute sd_attrs[TOTAL_ATTRS]; - char attr_name[TOTAL_ATTRS][CORETEMP_NAME_LENGTH]; - struct mutex update_lock; -}; - -/* Platform Data per Physical CPU */ -struct platform_data { - struct device *hwmon_dev; - u16 phys_proc_id; - struct temp_data *core_data[MAX_CORE_DATA]; - struct device_attribute name_attr; -}; - -struct pdev_entry { - struct list_head list; - struct platform_device *pdev; - u16 phys_proc_id; -}; - -static LIST_HEAD(pdev_list); -static DEFINE_MUTEX(pdev_list_mutex); - -static ssize_t show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - return sprintf(buf, "%s\n", DRVNAME); -} - -static ssize_t show_label(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct platform_data *pdata = dev_get_drvdata(dev); - struct temp_data *tdata = pdata->core_data[attr->index]; - - if (tdata->is_pkg_data) - return sprintf(buf, "Physical id %u\n", pdata->phys_proc_id); - - return sprintf(buf, "Core %u\n", tdata->cpu_core_id); -} - -static ssize_t show_crit_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - u32 eax, edx; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct platform_data *pdata = dev_get_drvdata(dev); - struct temp_data *tdata = pdata->core_data[attr->index]; - - rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); - - return sprintf(buf, "%d\n", (eax >> 5) & 1); -} - -static ssize_t show_tjmax(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct platform_data *pdata = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", pdata->core_data[attr->index]->tjmax); -} - -static ssize_t show_ttarget(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct platform_data *pdata = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", pdata->core_data[attr->index]->ttarget); -} - -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - u32 eax, edx; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct platform_data *pdata = dev_get_drvdata(dev); - struct temp_data *tdata = pdata->core_data[attr->index]; - - mutex_lock(&tdata->update_lock); - - /* Check whether the time interval has elapsed */ - if (!tdata->valid || time_after(jiffies, tdata->last_updated + HZ)) { - rdmsr_on_cpu(tdata->cpu, tdata->status_reg, &eax, &edx); - tdata->valid = 0; - /* Check whether the data is valid */ - if (eax & 0x80000000) { - tdata->temp = tdata->tjmax - - ((eax >> 16) & 0x7f) * 1000; - tdata->valid = 1; - } - tdata->last_updated = jiffies; - } - - mutex_unlock(&tdata->update_lock); - return tdata->valid ? sprintf(buf, "%d\n", tdata->temp) : -EAGAIN; -} - -static int __cpuinit adjust_tjmax(struct cpuinfo_x86 *c, u32 id, - struct device *dev) -{ - /* The 100C is default for both mobile and non mobile CPUs */ - - int tjmax = 100000; - int tjmax_ee = 85000; - int usemsr_ee = 1; - int err; - u32 eax, edx; - struct pci_dev *host_bridge; - - /* Early chips have no MSR for TjMax */ - - if (c->x86_model == 0xf && c->x86_mask < 4) - usemsr_ee = 0; - - /* Atom CPUs */ - - if (c->x86_model == 0x1c) { - usemsr_ee = 0; - - host_bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 0)); - - if (host_bridge && host_bridge->vendor == PCI_VENDOR_ID_INTEL - && (host_bridge->device == 0xa000 /* NM10 based nettop */ - || host_bridge->device == 0xa010)) /* NM10 based netbook */ - tjmax = 100000; - else - tjmax = 90000; - - pci_dev_put(host_bridge); - } - - if (c->x86_model > 0xe && usemsr_ee) { - u8 platform_id; - - /* - * Now we can detect the mobile CPU using Intel provided table - * http://softwarecommunity.intel.com/Wiki/Mobility/720.htm - * For Core2 cores, check MSR 0x17, bit 28 1 = Mobile CPU - */ - err = rdmsr_safe_on_cpu(id, 0x17, &eax, &edx); - if (err) { - dev_warn(dev, - "Unable to access MSR 0x17, assuming desktop" - " CPU\n"); - usemsr_ee = 0; - } else if (c->x86_model < 0x17 && !(eax & 0x10000000)) { - /* - * Trust bit 28 up to Penryn, I could not find any - * documentation on that; if you happen to know - * someone at Intel please ask - */ - usemsr_ee = 0; - } else { - /* Platform ID bits 52:50 (EDX starts at bit 32) */ - platform_id = (edx >> 18) & 0x7; - - /* - * Mobile Penryn CPU seems to be platform ID 7 or 5 - * (guesswork) - */ - if (c->x86_model == 0x17 && - (platform_id == 5 || platform_id == 7)) { - /* - * If MSR EE bit is set, set it to 90 degrees C, - * otherwise 105 degrees C - */ - tjmax_ee = 90000; - tjmax = 105000; - } - } - } - - if (usemsr_ee) { - err = rdmsr_safe_on_cpu(id, 0xee, &eax, &edx); - if (err) { - dev_warn(dev, - "Unable to access MSR 0xEE, for Tjmax, left" - " at default\n"); - } else if (eax & 0x40000000) { - tjmax = tjmax_ee; - } - } else if (tjmax == 100000) { - /* - * If we don't use msr EE it means we are desktop CPU - * (with exeception of Atom) - */ - dev_warn(dev, "Using relative temperature scale!\n"); - } - - return tjmax; -} - -static int __cpuinit get_tjmax(struct cpuinfo_x86 *c, u32 id, - struct device *dev) -{ - int err; - u32 eax, edx; - u32 val; - - /* - * A new feature of current Intel(R) processors, the - * IA32_TEMPERATURE_TARGET contains the TjMax value - */ - err = rdmsr_safe_on_cpu(id, MSR_IA32_TEMPERATURE_TARGET, &eax, &edx); - if (err) { - if (c->x86_model > 0xe && c->x86_model != 0x1c) - dev_warn(dev, "Unable to read TjMax from CPU %u\n", id); - } else { - val = (eax >> 16) & 0xff; - /* - * If the TjMax is not plausible, an assumption - * will be used - */ - if (val) { - dev_dbg(dev, "TjMax is %d degrees C\n", val); - return val * 1000; - } - } - - if (force_tjmax) { - dev_notice(dev, "TjMax forced to %d degrees C by user\n", - force_tjmax); - return force_tjmax * 1000; - } - - /* - * An assumption is made for early CPUs and unreadable MSR. - * NOTE: the calculated value may not be correct. - */ - return adjust_tjmax(c, id, dev); -} - -static int __devinit create_name_attr(struct platform_data *pdata, - struct device *dev) -{ - sysfs_attr_init(&pdata->name_attr.attr); - pdata->name_attr.attr.name = "name"; - pdata->name_attr.attr.mode = S_IRUGO; - pdata->name_attr.show = show_name; - return device_create_file(dev, &pdata->name_attr); -} - -static int __cpuinit create_core_attrs(struct temp_data *tdata, - struct device *dev, int attr_no) -{ - int err, i; - static ssize_t (*const rd_ptr[TOTAL_ATTRS]) (struct device *dev, - struct device_attribute *devattr, char *buf) = { - show_label, show_crit_alarm, show_temp, show_tjmax, - show_ttarget }; - static const char *const names[TOTAL_ATTRS] = { - "temp%d_label", "temp%d_crit_alarm", - "temp%d_input", "temp%d_crit", - "temp%d_max" }; - - for (i = 0; i < tdata->attr_size; i++) { - snprintf(tdata->attr_name[i], CORETEMP_NAME_LENGTH, names[i], - attr_no); - sysfs_attr_init(&tdata->sd_attrs[i].dev_attr.attr); - tdata->sd_attrs[i].dev_attr.attr.name = tdata->attr_name[i]; - tdata->sd_attrs[i].dev_attr.attr.mode = S_IRUGO; - tdata->sd_attrs[i].dev_attr.show = rd_ptr[i]; - tdata->sd_attrs[i].index = attr_no; - err = device_create_file(dev, &tdata->sd_attrs[i].dev_attr); - if (err) - goto exit_free; - } - return 0; - -exit_free: - while (--i >= 0) - device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); - return err; -} - - -static int __cpuinit chk_ucode_version(unsigned int cpu) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu); - - /* - * Check if we have problem with errata AE18 of Core processors: - * Readings might stop update when processor visited too deep sleep, - * fixed for stepping D0 (6EC). - */ - if (c->x86_model == 0xe && c->x86_mask < 0xc && c->microcode < 0x39) { - pr_err("Errata AE18 not fixed, update BIOS or " - "microcode of the CPU!\n"); - return -ENODEV; - } - return 0; -} - -static struct platform_device __cpuinit *coretemp_get_pdev(unsigned int cpu) -{ - u16 phys_proc_id = TO_PHYS_ID(cpu); - struct pdev_entry *p; - - mutex_lock(&pdev_list_mutex); - - list_for_each_entry(p, &pdev_list, list) - if (p->phys_proc_id == phys_proc_id) { - mutex_unlock(&pdev_list_mutex); - return p->pdev; - } - - mutex_unlock(&pdev_list_mutex); - return NULL; -} - -static struct temp_data __cpuinit *init_temp_data(unsigned int cpu, - int pkg_flag) -{ - struct temp_data *tdata; - - tdata = kzalloc(sizeof(struct temp_data), GFP_KERNEL); - if (!tdata) - return NULL; - - tdata->status_reg = pkg_flag ? MSR_IA32_PACKAGE_THERM_STATUS : - MSR_IA32_THERM_STATUS; - tdata->is_pkg_data = pkg_flag; - tdata->cpu = cpu; - tdata->cpu_core_id = TO_CORE_ID(cpu); - tdata->attr_size = MAX_CORE_ATTRS; - mutex_init(&tdata->update_lock); - return tdata; -} - -static int __cpuinit create_core_data(struct platform_device *pdev, - unsigned int cpu, int pkg_flag) -{ - struct temp_data *tdata; - struct platform_data *pdata = platform_get_drvdata(pdev); - struct cpuinfo_x86 *c = &cpu_data(cpu); - u32 eax, edx; - int err, attr_no; - - /* - * Find attr number for sysfs: - * We map the attr number to core id of the CPU - * The attr number is always core id + 2 - * The Pkgtemp will always show up as temp1_*, if available - */ - attr_no = pkg_flag ? 1 : TO_ATTR_NO(cpu); - - if (attr_no > MAX_CORE_DATA - 1) - return -ERANGE; - - /* - * Provide a single set of attributes for all HT siblings of a core - * to avoid duplicate sensors (the processor ID and core ID of all - * HT siblings of a core are the same). - * Skip if a HT sibling of this core is already registered. - * This is not an error. - */ - if (pdata->core_data[attr_no] != NULL) - return 0; - - tdata = init_temp_data(cpu, pkg_flag); - if (!tdata) - return -ENOMEM; - - /* Test if we can access the status register */ - err = rdmsr_safe_on_cpu(cpu, tdata->status_reg, &eax, &edx); - if (err) - goto exit_free; - - /* We can access status register. Get Critical Temperature */ - tdata->tjmax = get_tjmax(c, cpu, &pdev->dev); - - /* - * Read the still undocumented bits 8:15 of IA32_TEMPERATURE_TARGET. - * The target temperature is available on older CPUs but not in this - * register. Atoms don't have the register at all. - */ - if (c->x86_model > 0xe && c->x86_model != 0x1c) { - err = rdmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, - &eax, &edx); - if (!err) { - tdata->ttarget - = tdata->tjmax - ((eax >> 8) & 0xff) * 1000; - tdata->attr_size++; - } - } - - pdata->core_data[attr_no] = tdata; - - /* Create sysfs interfaces */ - err = create_core_attrs(tdata, &pdev->dev, attr_no); - if (err) - goto exit_free; - - return 0; -exit_free: - pdata->core_data[attr_no] = NULL; - kfree(tdata); - return err; -} - -static void __cpuinit coretemp_add_core(unsigned int cpu, int pkg_flag) -{ - struct platform_device *pdev = coretemp_get_pdev(cpu); - int err; - - if (!pdev) - return; - - err = create_core_data(pdev, cpu, pkg_flag); - if (err) - dev_err(&pdev->dev, "Adding Core %u failed\n", cpu); -} - -static void coretemp_remove_core(struct platform_data *pdata, - struct device *dev, int indx) -{ - int i; - struct temp_data *tdata = pdata->core_data[indx]; - - /* Remove the sysfs attributes */ - for (i = 0; i < tdata->attr_size; i++) - device_remove_file(dev, &tdata->sd_attrs[i].dev_attr); - - kfree(pdata->core_data[indx]); - pdata->core_data[indx] = NULL; -} - -static int __devinit coretemp_probe(struct platform_device *pdev) -{ - struct platform_data *pdata; - int err; - - /* Initialize the per-package data structures */ - pdata = kzalloc(sizeof(struct platform_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - err = create_name_attr(pdata, &pdev->dev); - if (err) - goto exit_free; - - pdata->phys_proc_id = pdev->id; - platform_set_drvdata(pdev, pdata); - - pdata->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(pdata->hwmon_dev)) { - err = PTR_ERR(pdata->hwmon_dev); - dev_err(&pdev->dev, "Class registration failed (%d)\n", err); - goto exit_name; - } - return 0; - -exit_name: - device_remove_file(&pdev->dev, &pdata->name_attr); - platform_set_drvdata(pdev, NULL); -exit_free: - kfree(pdata); - return err; -} - -static int __devexit coretemp_remove(struct platform_device *pdev) -{ - struct platform_data *pdata = platform_get_drvdata(pdev); - int i; - - for (i = MAX_CORE_DATA - 1; i >= 0; --i) - if (pdata->core_data[i]) - coretemp_remove_core(pdata, &pdev->dev, i); - - device_remove_file(&pdev->dev, &pdata->name_attr); - hwmon_device_unregister(pdata->hwmon_dev); - platform_set_drvdata(pdev, NULL); - kfree(pdata); - return 0; -} - -static struct platform_driver coretemp_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = coretemp_probe, - .remove = __devexit_p(coretemp_remove), -}; - -static int __cpuinit coretemp_device_add(unsigned int cpu) -{ - int err; - struct platform_device *pdev; - struct pdev_entry *pdev_entry; - - mutex_lock(&pdev_list_mutex); - - pdev = platform_device_alloc(DRVNAME, TO_PHYS_ID(cpu)); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); - if (!pdev_entry) { - err = -ENOMEM; - goto exit_device_put; - } - - err = platform_device_add(pdev); - if (err) { - pr_err("Device addition failed (%d)\n", err); - goto exit_device_free; - } - - pdev_entry->pdev = pdev; - pdev_entry->phys_proc_id = pdev->id; - - list_add_tail(&pdev_entry->list, &pdev_list); - mutex_unlock(&pdev_list_mutex); - - return 0; - -exit_device_free: - kfree(pdev_entry); -exit_device_put: - platform_device_put(pdev); -exit: - mutex_unlock(&pdev_list_mutex); - return err; -} - -static void __cpuinit coretemp_device_remove(unsigned int cpu) -{ - struct pdev_entry *p, *n; - u16 phys_proc_id = TO_PHYS_ID(cpu); - - mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - if (p->phys_proc_id != phys_proc_id) - continue; - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } - mutex_unlock(&pdev_list_mutex); -} - -static bool __cpuinit is_any_core_online(struct platform_data *pdata) -{ - int i; - - /* Find online cores, except pkgtemp data */ - for (i = MAX_CORE_DATA - 1; i >= 0; --i) { - if (pdata->core_data[i] && - !pdata->core_data[i]->is_pkg_data) { - return true; - } - } - return false; -} - -static void __cpuinit get_core_online(unsigned int cpu) -{ - struct cpuinfo_x86 *c = &cpu_data(cpu); - struct platform_device *pdev = coretemp_get_pdev(cpu); - int err; - - /* - * CPUID.06H.EAX[0] indicates whether the CPU has thermal - * sensors. We check this bit only, all the early CPUs - * without thermal sensors will be filtered out. - */ - if (!cpu_has(c, X86_FEATURE_DTHERM)) - return; - - if (!pdev) { - /* Check the microcode version of the CPU */ - if (chk_ucode_version(cpu)) - return; - - /* - * Alright, we have DTS support. - * We are bringing the _first_ core in this pkg - * online. So, initialize per-pkg data structures and - * then bring this core online. - */ - err = coretemp_device_add(cpu); - if (err) - return; - /* - * Check whether pkgtemp support is available. - * If so, add interfaces for pkgtemp. - */ - if (cpu_has(c, X86_FEATURE_PTS)) - coretemp_add_core(cpu, 1); - } - /* - * Physical CPU device already exists. - * So, just add interfaces for this core. - */ - coretemp_add_core(cpu, 0); -} - -static void __cpuinit put_core_offline(unsigned int cpu) -{ - int i, indx; - struct platform_data *pdata; - struct platform_device *pdev = coretemp_get_pdev(cpu); - - /* If the physical CPU device does not exist, just return */ - if (!pdev) - return; - - pdata = platform_get_drvdata(pdev); - - indx = TO_ATTR_NO(cpu); - - /* The core id is too big, just return */ - if (indx > MAX_CORE_DATA - 1) - return; - - if (pdata->core_data[indx] && pdata->core_data[indx]->cpu == cpu) - coretemp_remove_core(pdata, &pdev->dev, indx); - - /* - * If a HT sibling of a core is taken offline, but another HT sibling - * of the same core is still online, register the alternate sibling. - * This ensures that exactly one set of attributes is provided as long - * as at least one HT sibling of a core is online. - */ - for_each_sibling(i, cpu) { - if (i != cpu) { - get_core_online(i); - /* - * Display temperature sensor data for one HT sibling - * per core only, so abort the loop after one such - * sibling has been found. - */ - break; - } - } - /* - * If all cores in this pkg are offline, remove the device. - * coretemp_device_remove calls unregister_platform_device, - * which in turn calls coretemp_remove. This removes the - * pkgtemp entry and does other clean ups. - */ - if (!is_any_core_online(pdata)) - coretemp_device_remove(cpu); -} - -static int __cpuinit coretemp_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long) hcpu; - - switch (action) { - case CPU_ONLINE: - case CPU_DOWN_FAILED: - get_core_online(cpu); - break; - case CPU_DOWN_PREPARE: - put_core_offline(cpu); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block coretemp_cpu_notifier __refdata = { - .notifier_call = coretemp_cpu_callback, -}; - -static const struct x86_cpu_id coretemp_ids[] = { - { X86_VENDOR_INTEL, X86_FAMILY_ANY, X86_MODEL_ANY, X86_FEATURE_DTHERM }, - {} -}; -MODULE_DEVICE_TABLE(x86cpu, coretemp_ids); - -static int __init coretemp_init(void) -{ - int i, err = -ENODEV; - - /* - * CPUID.06H.EAX[0] indicates whether the CPU has thermal - * sensors. We check this bit only, all the early CPUs - * without thermal sensors will be filtered out. - */ - if (!x86_match_cpu(coretemp_ids)) - return -ENODEV; - - err = platform_driver_register(&coretemp_driver); - if (err) - goto exit; - - for_each_online_cpu(i) - get_core_online(i); - -#ifndef CONFIG_HOTPLUG_CPU - if (list_empty(&pdev_list)) { - err = -ENODEV; - goto exit_driver_unreg; - } -#endif - - register_hotcpu_notifier(&coretemp_cpu_notifier); - return 0; - -#ifndef CONFIG_HOTPLUG_CPU -exit_driver_unreg: - platform_driver_unregister(&coretemp_driver); -#endif -exit: - return err; -} - -static void __exit coretemp_exit(void) -{ - struct pdev_entry *p, *n; - - unregister_hotcpu_notifier(&coretemp_cpu_notifier); - mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } - mutex_unlock(&pdev_list_mutex); - platform_driver_unregister(&coretemp_driver); -} - -MODULE_AUTHOR("Rudolf Marek "); -MODULE_DESCRIPTION("Intel Core temperature monitor"); -MODULE_LICENSE("GPL"); - -module_init(coretemp_init) -module_exit(coretemp_exit) diff --git a/ANDROID_3.4.5/drivers/hwmon/dme1737.c b/ANDROID_3.4.5/drivers/hwmon/dme1737.c deleted file mode 100644 index e7c6a19f..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/dme1737.c +++ /dev/null @@ -1,2815 +0,0 @@ -/* - * dme1737.c - Driver for the SMSC DME1737, Asus A8000, SMSC SCH311x, SCH5027, - * and SCH5127 Super-I/O chips integrated hardware monitoring - * features. - * Copyright (c) 2007, 2008, 2009, 2010 Juerg Haefliger - * - * This driver is an I2C/ISA hybrid, meaning that it uses the I2C bus to access - * the chip registers if a DME1737, A8000, or SCH5027 is found and the ISA bus - * if a SCH311x or SCH5127 chip is found. Both types of chips have very - * similar hardware monitoring capabilities but differ in the way they can be - * accessed. - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* ISA device, if found */ -static struct platform_device *pdev; - -/* Module load parameters */ -static bool force_start; -module_param(force_start, bool, 0); -MODULE_PARM_DESC(force_start, "Force the chip to start monitoring inputs"); - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static bool probe_all_addr; -module_param(probe_all_addr, bool, 0); -MODULE_PARM_DESC(probe_all_addr, "Include probing of non-standard LPC " - "addresses"); - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END}; - -enum chips { dme1737, sch5027, sch311x, sch5127 }; - -/* --------------------------------------------------------------------- - * Registers - * - * The sensors are defined as follows: - * - * Voltages Temperatures - * -------- ------------ - * in0 +5VTR (+5V stdby) temp1 Remote diode 1 - * in1 Vccp (proc core) temp2 Internal temp - * in2 VCC (internal +3.3V) temp3 Remote diode 2 - * in3 +5V - * in4 +12V - * in5 VTR (+3.3V stby) - * in6 Vbat - * in7 Vtrip (sch5127 only) - * - * --------------------------------------------------------------------- */ - -/* Voltages (in) numbered 0-7 (ix) */ -#define DME1737_REG_IN(ix) ((ix) < 5 ? 0x20 + (ix) : \ - (ix) < 7 ? 0x94 + (ix) : \ - 0x1f) -#define DME1737_REG_IN_MIN(ix) ((ix) < 5 ? 0x44 + (ix) * 2 \ - : 0x91 + (ix) * 2) -#define DME1737_REG_IN_MAX(ix) ((ix) < 5 ? 0x45 + (ix) * 2 \ - : 0x92 + (ix) * 2) - -/* Temperatures (temp) numbered 0-2 (ix) */ -#define DME1737_REG_TEMP(ix) (0x25 + (ix)) -#define DME1737_REG_TEMP_MIN(ix) (0x4e + (ix) * 2) -#define DME1737_REG_TEMP_MAX(ix) (0x4f + (ix) * 2) -#define DME1737_REG_TEMP_OFFSET(ix) ((ix) == 0 ? 0x1f \ - : 0x1c + (ix)) - -/* - * Voltage and temperature LSBs - * The LSBs (4 bits each) are stored in 5 registers with the following layouts: - * IN_TEMP_LSB(0) = [in5, in6] - * IN_TEMP_LSB(1) = [temp3, temp1] - * IN_TEMP_LSB(2) = [in4, temp2] - * IN_TEMP_LSB(3) = [in3, in0] - * IN_TEMP_LSB(4) = [in2, in1] - * IN_TEMP_LSB(5) = [res, in7] - */ -#define DME1737_REG_IN_TEMP_LSB(ix) (0x84 + (ix)) -static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0, 5}; -static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4, 4}; -static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1}; -static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0}; - -/* Fans numbered 0-5 (ix) */ -#define DME1737_REG_FAN(ix) ((ix) < 4 ? 0x28 + (ix) * 2 \ - : 0xa1 + (ix) * 2) -#define DME1737_REG_FAN_MIN(ix) ((ix) < 4 ? 0x54 + (ix) * 2 \ - : 0xa5 + (ix) * 2) -#define DME1737_REG_FAN_OPT(ix) ((ix) < 4 ? 0x90 + (ix) \ - : 0xb2 + (ix)) -#define DME1737_REG_FAN_MAX(ix) (0xb4 + (ix)) /* only for fan[4-5] */ - -/* PWMs numbered 0-2, 4-5 (ix) */ -#define DME1737_REG_PWM(ix) ((ix) < 3 ? 0x30 + (ix) \ - : 0xa1 + (ix)) -#define DME1737_REG_PWM_CONFIG(ix) (0x5c + (ix)) /* only for pwm[0-2] */ -#define DME1737_REG_PWM_MIN(ix) (0x64 + (ix)) /* only for pwm[0-2] */ -#define DME1737_REG_PWM_FREQ(ix) ((ix) < 3 ? 0x5f + (ix) \ - : 0xa3 + (ix)) -/* - * The layout of the ramp rate registers is different from the other pwm - * registers. The bits for the 3 PWMs are stored in 2 registers: - * PWM_RR(0) = [OFF3, OFF2, OFF1, RES, RR1E, RR1-2, RR1-1, RR1-0] - * PWM_RR(1) = [RR2E, RR2-2, RR2-1, RR2-0, RR3E, RR3-2, RR3-1, RR3-0] - */ -#define DME1737_REG_PWM_RR(ix) (0x62 + (ix)) /* only for pwm[0-2] */ - -/* Thermal zones 0-2 */ -#define DME1737_REG_ZONE_LOW(ix) (0x67 + (ix)) -#define DME1737_REG_ZONE_ABS(ix) (0x6a + (ix)) -/* - * The layout of the hysteresis registers is different from the other zone - * registers. The bits for the 3 zones are stored in 2 registers: - * ZONE_HYST(0) = [H1-3, H1-2, H1-1, H1-0, H2-3, H2-2, H2-1, H2-0] - * ZONE_HYST(1) = [H3-3, H3-2, H3-1, H3-0, RES, RES, RES, RES] - */ -#define DME1737_REG_ZONE_HYST(ix) (0x6d + (ix)) - -/* - * Alarm registers and bit mapping - * The 3 8-bit alarm registers will be concatenated to a single 32-bit - * alarm value [0, ALARM3, ALARM2, ALARM1]. - */ -#define DME1737_REG_ALARM1 0x41 -#define DME1737_REG_ALARM2 0x42 -#define DME1737_REG_ALARM3 0x83 -static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17, 18}; -static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6}; -static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23}; - -/* Miscellaneous registers */ -#define DME1737_REG_DEVICE 0x3d -#define DME1737_REG_COMPANY 0x3e -#define DME1737_REG_VERSTEP 0x3f -#define DME1737_REG_CONFIG 0x40 -#define DME1737_REG_CONFIG2 0x7f -#define DME1737_REG_VID 0x43 -#define DME1737_REG_TACH_PWM 0x81 - -/* --------------------------------------------------------------------- - * Misc defines - * --------------------------------------------------------------------- */ - -/* Chip identification */ -#define DME1737_COMPANY_SMSC 0x5c -#define DME1737_VERSTEP 0x88 -#define DME1737_VERSTEP_MASK 0xf8 -#define SCH311X_DEVICE 0x8c -#define SCH5027_VERSTEP 0x69 -#define SCH5127_DEVICE 0x8e - -/* Device ID values (global configuration register index 0x20) */ -#define DME1737_ID_1 0x77 -#define DME1737_ID_2 0x78 -#define SCH3112_ID 0x7c -#define SCH3114_ID 0x7d -#define SCH3116_ID 0x7f -#define SCH5027_ID 0x89 -#define SCH5127_ID 0x86 - -/* Length of ISA address segment */ -#define DME1737_EXTENT 2 - -/* chip-dependent features */ -#define HAS_TEMP_OFFSET (1 << 0) /* bit 0 */ -#define HAS_VID (1 << 1) /* bit 1 */ -#define HAS_ZONE3 (1 << 2) /* bit 2 */ -#define HAS_ZONE_HYST (1 << 3) /* bit 3 */ -#define HAS_PWM_MIN (1 << 4) /* bit 4 */ -#define HAS_FAN(ix) (1 << ((ix) + 5)) /* bits 5-10 */ -#define HAS_PWM(ix) (1 << ((ix) + 11)) /* bits 11-16 */ -#define HAS_IN7 (1 << 17) /* bit 17 */ - -/* --------------------------------------------------------------------- - * Data structures and manipulation thereof - * --------------------------------------------------------------------- */ - -struct dme1737_data { - struct i2c_client *client; /* for I2C devices only */ - struct device *hwmon_dev; - const char *name; - unsigned int addr; /* for ISA devices only */ - - struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ - unsigned long last_update; /* in jiffies */ - unsigned long last_vbat; /* in jiffies */ - enum chips type; - const int *in_nominal; /* pointer to IN_NOMINAL array */ - - u8 vid; - u8 pwm_rr_en; - u32 has_features; - - /* Register values */ - u16 in[8]; - u8 in_min[8]; - u8 in_max[8]; - s16 temp[3]; - s8 temp_min[3]; - s8 temp_max[3]; - s8 temp_offset[3]; - u8 config; - u8 config2; - u8 vrm; - u16 fan[6]; - u16 fan_min[6]; - u8 fan_max[2]; - u8 fan_opt[6]; - u8 pwm[6]; - u8 pwm_min[3]; - u8 pwm_config[3]; - u8 pwm_acz[3]; - u8 pwm_freq[6]; - u8 pwm_rr[2]; - u8 zone_low[3]; - u8 zone_abs[3]; - u8 zone_hyst[2]; - u32 alarms; -}; - -/* Nominal voltage values */ -static const int IN_NOMINAL_DME1737[] = {5000, 2250, 3300, 5000, 12000, 3300, - 3300}; -static const int IN_NOMINAL_SCH311x[] = {2500, 1500, 3300, 5000, 12000, 3300, - 3300}; -static const int IN_NOMINAL_SCH5027[] = {5000, 2250, 3300, 1125, 1125, 3300, - 3300}; -static const int IN_NOMINAL_SCH5127[] = {2500, 2250, 3300, 1125, 1125, 3300, - 3300, 1500}; -#define IN_NOMINAL(type) ((type) == sch311x ? IN_NOMINAL_SCH311x : \ - (type) == sch5027 ? IN_NOMINAL_SCH5027 : \ - (type) == sch5127 ? IN_NOMINAL_SCH5127 : \ - IN_NOMINAL_DME1737) - -/* - * Voltage input - * Voltage inputs have 16 bits resolution, limit values have 8 bits - * resolution. - */ -static inline int IN_FROM_REG(int reg, int nominal, int res) -{ - return (reg * nominal + (3 << (res - 3))) / (3 << (res - 2)); -} - -static inline int IN_TO_REG(int val, int nominal) -{ - return SENSORS_LIMIT((val * 192 + nominal / 2) / nominal, 0, 255); -} - -/* - * Temperature input - * The register values represent temperatures in 2's complement notation from - * -127 degrees C to +127 degrees C. Temp inputs have 16 bits resolution, limit - * values have 8 bits resolution. - */ -static inline int TEMP_FROM_REG(int reg, int res) -{ - return (reg * 1000) >> (res - 8); -} - -static inline int TEMP_TO_REG(int val) -{ - return SENSORS_LIMIT((val < 0 ? val - 500 : val + 500) / 1000, - -128, 127); -} - -/* Temperature range */ -static const int TEMP_RANGE[] = {2000, 2500, 3333, 4000, 5000, 6666, 8000, - 10000, 13333, 16000, 20000, 26666, 32000, - 40000, 53333, 80000}; - -static inline int TEMP_RANGE_FROM_REG(int reg) -{ - return TEMP_RANGE[(reg >> 4) & 0x0f]; -} - -static int TEMP_RANGE_TO_REG(int val, int reg) -{ - int i; - - for (i = 15; i > 0; i--) { - if (val > (TEMP_RANGE[i] + TEMP_RANGE[i - 1] + 1) / 2) - break; - } - - return (reg & 0x0f) | (i << 4); -} - -/* - * Temperature hysteresis - * Register layout: - * reg[0] = [H1-3, H1-2, H1-1, H1-0, H2-3, H2-2, H2-1, H2-0] - * reg[1] = [H3-3, H3-2, H3-1, H3-0, xxxx, xxxx, xxxx, xxxx] - */ -static inline int TEMP_HYST_FROM_REG(int reg, int ix) -{ - return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000; -} - -static inline int TEMP_HYST_TO_REG(int val, int ix, int reg) -{ - int hyst = SENSORS_LIMIT((val + 500) / 1000, 0, 15); - - return (ix == 1) ? (reg & 0xf0) | hyst : (reg & 0x0f) | (hyst << 4); -} - -/* Fan input RPM */ -static inline int FAN_FROM_REG(int reg, int tpc) -{ - if (tpc) - return tpc * reg; - else - return (reg == 0 || reg == 0xffff) ? 0 : 90000 * 60 / reg; -} - -static inline int FAN_TO_REG(int val, int tpc) -{ - if (tpc) { - return SENSORS_LIMIT(val / tpc, 0, 0xffff); - } else { - return (val <= 0) ? 0xffff : - SENSORS_LIMIT(90000 * 60 / val, 0, 0xfffe); - } -} - -/* - * Fan TPC (tach pulse count) - * Converts a register value to a TPC multiplier or returns 0 if the tachometer - * is configured in legacy (non-tpc) mode - */ -static inline int FAN_TPC_FROM_REG(int reg) -{ - return (reg & 0x20) ? 0 : 60 >> (reg & 0x03); -} - -/* - * Fan type - * The type of a fan is expressed in number of pulses-per-revolution that it - * emits - */ -static inline int FAN_TYPE_FROM_REG(int reg) -{ - int edge = (reg >> 1) & 0x03; - - return (edge > 0) ? 1 << (edge - 1) : 0; -} - -static inline int FAN_TYPE_TO_REG(int val, int reg) -{ - int edge = (val == 4) ? 3 : val; - - return (reg & 0xf9) | (edge << 1); -} - -/* Fan max RPM */ -static const int FAN_MAX[] = {0x54, 0x38, 0x2a, 0x21, 0x1c, 0x18, 0x15, 0x12, - 0x11, 0x0f, 0x0e}; - -static int FAN_MAX_FROM_REG(int reg) -{ - int i; - - for (i = 10; i > 0; i--) { - if (reg == FAN_MAX[i]) - break; - } - - return 1000 + i * 500; -} - -static int FAN_MAX_TO_REG(int val) -{ - int i; - - for (i = 10; i > 0; i--) { - if (val > (1000 + (i - 1) * 500)) - break; - } - - return FAN_MAX[i]; -} - -/* - * PWM enable - * Register to enable mapping: - * 000: 2 fan on zone 1 auto - * 001: 2 fan on zone 2 auto - * 010: 2 fan on zone 3 auto - * 011: 0 fan full on - * 100: -1 fan disabled - * 101: 2 fan on hottest of zones 2,3 auto - * 110: 2 fan on hottest of zones 1,2,3 auto - * 111: 1 fan in manual mode - */ -static inline int PWM_EN_FROM_REG(int reg) -{ - static const int en[] = {2, 2, 2, 0, -1, 2, 2, 1}; - - return en[(reg >> 5) & 0x07]; -} - -static inline int PWM_EN_TO_REG(int val, int reg) -{ - int en = (val == 1) ? 7 : 3; - - return (reg & 0x1f) | ((en & 0x07) << 5); -} - -/* - * PWM auto channels zone - * Register to auto channels zone mapping (ACZ is a bitfield with bit x - * corresponding to zone x+1): - * 000: 001 fan on zone 1 auto - * 001: 010 fan on zone 2 auto - * 010: 100 fan on zone 3 auto - * 011: 000 fan full on - * 100: 000 fan disabled - * 101: 110 fan on hottest of zones 2,3 auto - * 110: 111 fan on hottest of zones 1,2,3 auto - * 111: 000 fan in manual mode - */ -static inline int PWM_ACZ_FROM_REG(int reg) -{ - static const int acz[] = {1, 2, 4, 0, 0, 6, 7, 0}; - - return acz[(reg >> 5) & 0x07]; -} - -static inline int PWM_ACZ_TO_REG(int val, int reg) -{ - int acz = (val == 4) ? 2 : val - 1; - - return (reg & 0x1f) | ((acz & 0x07) << 5); -} - -/* PWM frequency */ -static const int PWM_FREQ[] = {11, 15, 22, 29, 35, 44, 59, 88, - 15000, 20000, 30000, 25000, 0, 0, 0, 0}; - -static inline int PWM_FREQ_FROM_REG(int reg) -{ - return PWM_FREQ[reg & 0x0f]; -} - -static int PWM_FREQ_TO_REG(int val, int reg) -{ - int i; - - /* the first two cases are special - stupid chip design! */ - if (val > 27500) { - i = 10; - } else if (val > 22500) { - i = 11; - } else { - for (i = 9; i > 0; i--) { - if (val > (PWM_FREQ[i] + PWM_FREQ[i - 1] + 1) / 2) - break; - } - } - - return (reg & 0xf0) | i; -} - -/* - * PWM ramp rate - * Register layout: - * reg[0] = [OFF3, OFF2, OFF1, RES, RR1-E, RR1-2, RR1-1, RR1-0] - * reg[1] = [RR2-E, RR2-2, RR2-1, RR2-0, RR3-E, RR3-2, RR3-1, RR3-0] - */ -static const u8 PWM_RR[] = {206, 104, 69, 41, 26, 18, 10, 5}; - -static inline int PWM_RR_FROM_REG(int reg, int ix) -{ - int rr = (ix == 1) ? reg >> 4 : reg; - - return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0; -} - -static int PWM_RR_TO_REG(int val, int ix, int reg) -{ - int i; - - for (i = 0; i < 7; i++) { - if (val > (PWM_RR[i] + PWM_RR[i + 1] + 1) / 2) - break; - } - - return (ix == 1) ? (reg & 0x8f) | (i << 4) : (reg & 0xf8) | i; -} - -/* PWM ramp rate enable */ -static inline int PWM_RR_EN_FROM_REG(int reg, int ix) -{ - return PWM_RR_FROM_REG(reg, ix) ? 1 : 0; -} - -static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg) -{ - int en = (ix == 1) ? 0x80 : 0x08; - - return val ? reg | en : reg & ~en; -} - -/* - * PWM min/off - * The PWM min/off bits are part of the PMW ramp rate register 0 (see above for - * the register layout). - */ -static inline int PWM_OFF_FROM_REG(int reg, int ix) -{ - return (reg >> (ix + 5)) & 0x01; -} - -static inline int PWM_OFF_TO_REG(int val, int ix, int reg) -{ - return (reg & ~(1 << (ix + 5))) | ((val & 0x01) << (ix + 5)); -} - -/* --------------------------------------------------------------------- - * Device I/O access - * - * ISA access is performed through an index/data register pair and needs to - * be protected by a mutex during runtime (not required for initialization). - * We use data->update_lock for this and need to ensure that we acquire it - * before calling dme1737_read or dme1737_write. - * --------------------------------------------------------------------- */ - -static u8 dme1737_read(const struct dme1737_data *data, u8 reg) -{ - struct i2c_client *client = data->client; - s32 val; - - if (client) { /* I2C device */ - val = i2c_smbus_read_byte_data(client, reg); - - if (val < 0) { - dev_warn(&client->dev, "Read from register " - "0x%02x failed! Please report to the driver " - "maintainer.\n", reg); - } - } else { /* ISA device */ - outb(reg, data->addr); - val = inb(data->addr + 1); - } - - return val; -} - -static s32 dme1737_write(const struct dme1737_data *data, u8 reg, u8 val) -{ - struct i2c_client *client = data->client; - s32 res = 0; - - if (client) { /* I2C device */ - res = i2c_smbus_write_byte_data(client, reg, val); - - if (res < 0) { - dev_warn(&client->dev, "Write to register " - "0x%02x failed! Please report to the driver " - "maintainer.\n", reg); - } - } else { /* ISA device */ - outb(reg, data->addr); - outb(val, data->addr + 1); - } - - return res; -} - -static struct dme1737_data *dme1737_update_device(struct device *dev) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - int ix; - u8 lsb[6]; - - mutex_lock(&data->update_lock); - - /* Enable a Vbat monitoring cycle every 10 mins */ - if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) { - dme1737_write(data, DME1737_REG_CONFIG, dme1737_read(data, - DME1737_REG_CONFIG) | 0x10); - data->last_vbat = jiffies; - } - - /* Sample register contents every 1 sec */ - if (time_after(jiffies, data->last_update + HZ) || !data->valid) { - if (data->has_features & HAS_VID) { - data->vid = dme1737_read(data, DME1737_REG_VID) & - 0x3f; - } - - /* In (voltage) registers */ - for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { - /* - * Voltage inputs are stored as 16 bit values even - * though they have only 12 bits resolution. This is - * to make it consistent with the temp inputs. - */ - if (ix == 7 && !(data->has_features & HAS_IN7)) - continue; - data->in[ix] = dme1737_read(data, - DME1737_REG_IN(ix)) << 8; - data->in_min[ix] = dme1737_read(data, - DME1737_REG_IN_MIN(ix)); - data->in_max[ix] = dme1737_read(data, - DME1737_REG_IN_MAX(ix)); - } - - /* Temp registers */ - for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { - /* - * Temp inputs are stored as 16 bit values even - * though they have only 12 bits resolution. This is - * to take advantage of implicit conversions between - * register values (2's complement) and temp values - * (signed decimal). - */ - data->temp[ix] = dme1737_read(data, - DME1737_REG_TEMP(ix)) << 8; - data->temp_min[ix] = dme1737_read(data, - DME1737_REG_TEMP_MIN(ix)); - data->temp_max[ix] = dme1737_read(data, - DME1737_REG_TEMP_MAX(ix)); - if (data->has_features & HAS_TEMP_OFFSET) { - data->temp_offset[ix] = dme1737_read(data, - DME1737_REG_TEMP_OFFSET(ix)); - } - } - - /* - * In and temp LSB registers - * The LSBs are latched when the MSBs are read, so the order in - * which the registers are read (MSB first, then LSB) is - * important! - */ - for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) { - if (ix == 5 && !(data->has_features & HAS_IN7)) - continue; - lsb[ix] = dme1737_read(data, - DME1737_REG_IN_TEMP_LSB(ix)); - } - for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { - if (ix == 7 && !(data->has_features & HAS_IN7)) - continue; - data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] << - DME1737_REG_IN_LSB_SHL[ix]) & 0xf0; - } - for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { - data->temp[ix] |= (lsb[DME1737_REG_TEMP_LSB[ix]] << - DME1737_REG_TEMP_LSB_SHL[ix]) & 0xf0; - } - - /* Fan registers */ - for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { - /* - * Skip reading registers if optional fans are not - * present - */ - if (!(data->has_features & HAS_FAN(ix))) - continue; - data->fan[ix] = dme1737_read(data, - DME1737_REG_FAN(ix)); - data->fan[ix] |= dme1737_read(data, - DME1737_REG_FAN(ix) + 1) << 8; - data->fan_min[ix] = dme1737_read(data, - DME1737_REG_FAN_MIN(ix)); - data->fan_min[ix] |= dme1737_read(data, - DME1737_REG_FAN_MIN(ix) + 1) << 8; - data->fan_opt[ix] = dme1737_read(data, - DME1737_REG_FAN_OPT(ix)); - /* fan_max exists only for fan[5-6] */ - if (ix > 3) { - data->fan_max[ix - 4] = dme1737_read(data, - DME1737_REG_FAN_MAX(ix)); - } - } - - /* PWM registers */ - for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) { - /* - * Skip reading registers if optional PWMs are not - * present - */ - if (!(data->has_features & HAS_PWM(ix))) - continue; - data->pwm[ix] = dme1737_read(data, - DME1737_REG_PWM(ix)); - data->pwm_freq[ix] = dme1737_read(data, - DME1737_REG_PWM_FREQ(ix)); - /* pwm_config and pwm_min exist only for pwm[1-3] */ - if (ix < 3) { - data->pwm_config[ix] = dme1737_read(data, - DME1737_REG_PWM_CONFIG(ix)); - data->pwm_min[ix] = dme1737_read(data, - DME1737_REG_PWM_MIN(ix)); - } - } - for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) { - data->pwm_rr[ix] = dme1737_read(data, - DME1737_REG_PWM_RR(ix)); - } - - /* Thermal zone registers */ - for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) { - /* Skip reading registers if zone3 is not present */ - if ((ix == 2) && !(data->has_features & HAS_ZONE3)) - continue; - /* sch5127 zone2 registers are special */ - if ((ix == 1) && (data->type == sch5127)) { - data->zone_low[1] = dme1737_read(data, - DME1737_REG_ZONE_LOW(2)); - data->zone_abs[1] = dme1737_read(data, - DME1737_REG_ZONE_ABS(2)); - } else { - data->zone_low[ix] = dme1737_read(data, - DME1737_REG_ZONE_LOW(ix)); - data->zone_abs[ix] = dme1737_read(data, - DME1737_REG_ZONE_ABS(ix)); - } - } - if (data->has_features & HAS_ZONE_HYST) { - for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) { - data->zone_hyst[ix] = dme1737_read(data, - DME1737_REG_ZONE_HYST(ix)); - } - } - - /* Alarm registers */ - data->alarms = dme1737_read(data, - DME1737_REG_ALARM1); - /* - * Bit 7 tells us if the other alarm registers are non-zero and - * therefore also need to be read - */ - if (data->alarms & 0x80) { - data->alarms |= dme1737_read(data, - DME1737_REG_ALARM2) << 8; - data->alarms |= dme1737_read(data, - DME1737_REG_ALARM3) << 16; - } - - /* - * The ISA chips require explicit clearing of alarm bits. - * Don't worry, an alarm will come back if the condition - * that causes it still exists - */ - if (!data->client) { - if (data->alarms & 0xff0000) - dme1737_write(data, DME1737_REG_ALARM3, 0xff); - if (data->alarms & 0xff00) - dme1737_write(data, DME1737_REG_ALARM2, 0xff); - if (data->alarms & 0xff) - dme1737_write(data, DME1737_REG_ALARM1, 0xff); - } - - data->last_update = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* --------------------------------------------------------------------- - * Voltage sysfs attributes - * ix = [0-7] - * --------------------------------------------------------------------- */ - -#define SYS_IN_INPUT 0 -#define SYS_IN_MIN 1 -#define SYS_IN_MAX 2 -#define SYS_IN_ALARM 3 - -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dme1737_update_device(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SYS_IN_INPUT: - res = IN_FROM_REG(data->in[ix], data->in_nominal[ix], 16); - break; - case SYS_IN_MIN: - res = IN_FROM_REG(data->in_min[ix], data->in_nominal[ix], 8); - break; - case SYS_IN_MAX: - res = IN_FROM_REG(data->in_max[ix], data->in_nominal[ix], 8); - break; - case SYS_IN_ALARM: - res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01; - break; - default: - res = 0; - dev_dbg(dev, "Unknown function %d.\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_in(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SYS_IN_MIN: - data->in_min[ix] = IN_TO_REG(val, data->in_nominal[ix]); - dme1737_write(data, DME1737_REG_IN_MIN(ix), - data->in_min[ix]); - break; - case SYS_IN_MAX: - data->in_max[ix] = IN_TO_REG(val, data->in_nominal[ix]); - dme1737_write(data, DME1737_REG_IN_MAX(ix), - data->in_max[ix]); - break; - default: - dev_dbg(dev, "Unknown function %d.\n", fn); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Temperature sysfs attributes - * ix = [0-2] - * --------------------------------------------------------------------- */ - -#define SYS_TEMP_INPUT 0 -#define SYS_TEMP_MIN 1 -#define SYS_TEMP_MAX 2 -#define SYS_TEMP_OFFSET 3 -#define SYS_TEMP_ALARM 4 -#define SYS_TEMP_FAULT 5 - -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dme1737_update_device(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SYS_TEMP_INPUT: - res = TEMP_FROM_REG(data->temp[ix], 16); - break; - case SYS_TEMP_MIN: - res = TEMP_FROM_REG(data->temp_min[ix], 8); - break; - case SYS_TEMP_MAX: - res = TEMP_FROM_REG(data->temp_max[ix], 8); - break; - case SYS_TEMP_OFFSET: - res = TEMP_FROM_REG(data->temp_offset[ix], 8); - break; - case SYS_TEMP_ALARM: - res = (data->alarms >> DME1737_BIT_ALARM_TEMP[ix]) & 0x01; - break; - case SYS_TEMP_FAULT: - res = (((u16)data->temp[ix] & 0xff00) == 0x8000); - break; - default: - res = 0; - dev_dbg(dev, "Unknown function %d.\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SYS_TEMP_MIN: - data->temp_min[ix] = TEMP_TO_REG(val); - dme1737_write(data, DME1737_REG_TEMP_MIN(ix), - data->temp_min[ix]); - break; - case SYS_TEMP_MAX: - data->temp_max[ix] = TEMP_TO_REG(val); - dme1737_write(data, DME1737_REG_TEMP_MAX(ix), - data->temp_max[ix]); - break; - case SYS_TEMP_OFFSET: - data->temp_offset[ix] = TEMP_TO_REG(val); - dme1737_write(data, DME1737_REG_TEMP_OFFSET(ix), - data->temp_offset[ix]); - break; - default: - dev_dbg(dev, "Unknown function %d.\n", fn); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Zone sysfs attributes - * ix = [0-2] - * --------------------------------------------------------------------- */ - -#define SYS_ZONE_AUTO_CHANNELS_TEMP 0 -#define SYS_ZONE_AUTO_POINT1_TEMP_HYST 1 -#define SYS_ZONE_AUTO_POINT1_TEMP 2 -#define SYS_ZONE_AUTO_POINT2_TEMP 3 -#define SYS_ZONE_AUTO_POINT3_TEMP 4 - -static ssize_t show_zone(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dme1737_update_device(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SYS_ZONE_AUTO_CHANNELS_TEMP: - /* check config2 for non-standard temp-to-zone mapping */ - if ((ix == 1) && (data->config2 & 0x02)) - res = 4; - else - res = 1 << ix; - break; - case SYS_ZONE_AUTO_POINT1_TEMP_HYST: - res = TEMP_FROM_REG(data->zone_low[ix], 8) - - TEMP_HYST_FROM_REG(data->zone_hyst[ix == 2], ix); - break; - case SYS_ZONE_AUTO_POINT1_TEMP: - res = TEMP_FROM_REG(data->zone_low[ix], 8); - break; - case SYS_ZONE_AUTO_POINT2_TEMP: - /* pwm_freq holds the temp range bits in the upper nibble */ - res = TEMP_FROM_REG(data->zone_low[ix], 8) + - TEMP_RANGE_FROM_REG(data->pwm_freq[ix]); - break; - case SYS_ZONE_AUTO_POINT3_TEMP: - res = TEMP_FROM_REG(data->zone_abs[ix], 8); - break; - default: - res = 0; - dev_dbg(dev, "Unknown function %d.\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_zone(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SYS_ZONE_AUTO_POINT1_TEMP_HYST: - /* Refresh the cache */ - data->zone_low[ix] = dme1737_read(data, - DME1737_REG_ZONE_LOW(ix)); - /* Modify the temp hyst value */ - data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG( - TEMP_FROM_REG(data->zone_low[ix], 8) - - val, ix, dme1737_read(data, - DME1737_REG_ZONE_HYST(ix == 2))); - dme1737_write(data, DME1737_REG_ZONE_HYST(ix == 2), - data->zone_hyst[ix == 2]); - break; - case SYS_ZONE_AUTO_POINT1_TEMP: - data->zone_low[ix] = TEMP_TO_REG(val); - dme1737_write(data, DME1737_REG_ZONE_LOW(ix), - data->zone_low[ix]); - break; - case SYS_ZONE_AUTO_POINT2_TEMP: - /* Refresh the cache */ - data->zone_low[ix] = dme1737_read(data, - DME1737_REG_ZONE_LOW(ix)); - /* - * Modify the temp range value (which is stored in the upper - * nibble of the pwm_freq register) - */ - data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val - - TEMP_FROM_REG(data->zone_low[ix], 8), - dme1737_read(data, - DME1737_REG_PWM_FREQ(ix))); - dme1737_write(data, DME1737_REG_PWM_FREQ(ix), - data->pwm_freq[ix]); - break; - case SYS_ZONE_AUTO_POINT3_TEMP: - data->zone_abs[ix] = TEMP_TO_REG(val); - dme1737_write(data, DME1737_REG_ZONE_ABS(ix), - data->zone_abs[ix]); - break; - default: - dev_dbg(dev, "Unknown function %d.\n", fn); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Fan sysfs attributes - * ix = [0-5] - * --------------------------------------------------------------------- */ - -#define SYS_FAN_INPUT 0 -#define SYS_FAN_MIN 1 -#define SYS_FAN_MAX 2 -#define SYS_FAN_ALARM 3 -#define SYS_FAN_TYPE 4 - -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dme1737_update_device(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SYS_FAN_INPUT: - res = FAN_FROM_REG(data->fan[ix], - ix < 4 ? 0 : - FAN_TPC_FROM_REG(data->fan_opt[ix])); - break; - case SYS_FAN_MIN: - res = FAN_FROM_REG(data->fan_min[ix], - ix < 4 ? 0 : - FAN_TPC_FROM_REG(data->fan_opt[ix])); - break; - case SYS_FAN_MAX: - /* only valid for fan[5-6] */ - res = FAN_MAX_FROM_REG(data->fan_max[ix - 4]); - break; - case SYS_FAN_ALARM: - res = (data->alarms >> DME1737_BIT_ALARM_FAN[ix]) & 0x01; - break; - case SYS_FAN_TYPE: - /* only valid for fan[1-4] */ - res = FAN_TYPE_FROM_REG(data->fan_opt[ix]); - break; - default: - res = 0; - dev_dbg(dev, "Unknown function %d.\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_fan(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SYS_FAN_MIN: - if (ix < 4) { - data->fan_min[ix] = FAN_TO_REG(val, 0); - } else { - /* Refresh the cache */ - data->fan_opt[ix] = dme1737_read(data, - DME1737_REG_FAN_OPT(ix)); - /* Modify the fan min value */ - data->fan_min[ix] = FAN_TO_REG(val, - FAN_TPC_FROM_REG(data->fan_opt[ix])); - } - dme1737_write(data, DME1737_REG_FAN_MIN(ix), - data->fan_min[ix] & 0xff); - dme1737_write(data, DME1737_REG_FAN_MIN(ix) + 1, - data->fan_min[ix] >> 8); - break; - case SYS_FAN_MAX: - /* Only valid for fan[5-6] */ - data->fan_max[ix - 4] = FAN_MAX_TO_REG(val); - dme1737_write(data, DME1737_REG_FAN_MAX(ix), - data->fan_max[ix - 4]); - break; - case SYS_FAN_TYPE: - /* Only valid for fan[1-4] */ - if (!(val == 1 || val == 2 || val == 4)) { - count = -EINVAL; - dev_warn(dev, "Fan type value %ld not " - "supported. Choose one of 1, 2, or 4.\n", - val); - goto exit; - } - data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(data, - DME1737_REG_FAN_OPT(ix))); - dme1737_write(data, DME1737_REG_FAN_OPT(ix), - data->fan_opt[ix]); - break; - default: - dev_dbg(dev, "Unknown function %d.\n", fn); - } -exit: - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * PWM sysfs attributes - * ix = [0-4] - * --------------------------------------------------------------------- */ - -#define SYS_PWM 0 -#define SYS_PWM_FREQ 1 -#define SYS_PWM_ENABLE 2 -#define SYS_PWM_RAMP_RATE 3 -#define SYS_PWM_AUTO_CHANNELS_ZONE 4 -#define SYS_PWM_AUTO_PWM_MIN 5 -#define SYS_PWM_AUTO_POINT1_PWM 6 -#define SYS_PWM_AUTO_POINT2_PWM 7 - -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dme1737_update_device(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SYS_PWM: - if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 0) - res = 255; - else - res = data->pwm[ix]; - break; - case SYS_PWM_FREQ: - res = PWM_FREQ_FROM_REG(data->pwm_freq[ix]); - break; - case SYS_PWM_ENABLE: - if (ix >= 3) - res = 1; /* pwm[5-6] hard-wired to manual mode */ - else - res = PWM_EN_FROM_REG(data->pwm_config[ix]); - break; - case SYS_PWM_RAMP_RATE: - /* Only valid for pwm[1-3] */ - res = PWM_RR_FROM_REG(data->pwm_rr[ix > 0], ix); - break; - case SYS_PWM_AUTO_CHANNELS_ZONE: - /* Only valid for pwm[1-3] */ - if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) - res = PWM_ACZ_FROM_REG(data->pwm_config[ix]); - else - res = data->pwm_acz[ix]; - break; - case SYS_PWM_AUTO_PWM_MIN: - /* Only valid for pwm[1-3] */ - if (PWM_OFF_FROM_REG(data->pwm_rr[0], ix)) - res = data->pwm_min[ix]; - else - res = 0; - break; - case SYS_PWM_AUTO_POINT1_PWM: - /* Only valid for pwm[1-3] */ - res = data->pwm_min[ix]; - break; - case SYS_PWM_AUTO_POINT2_PWM: - /* Only valid for pwm[1-3] */ - res = 255; /* hard-wired */ - break; - default: - res = 0; - dev_dbg(dev, "Unknown function %d.\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static struct attribute *dme1737_pwm_chmod_attr[]; -static void dme1737_chmod_file(struct device*, struct attribute*, umode_t); - -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 - *sensor_attr_2 = to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SYS_PWM: - data->pwm[ix] = SENSORS_LIMIT(val, 0, 255); - dme1737_write(data, DME1737_REG_PWM(ix), data->pwm[ix]); - break; - case SYS_PWM_FREQ: - data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(data, - DME1737_REG_PWM_FREQ(ix))); - dme1737_write(data, DME1737_REG_PWM_FREQ(ix), - data->pwm_freq[ix]); - break; - case SYS_PWM_ENABLE: - /* Only valid for pwm[1-3] */ - if (val < 0 || val > 2) { - count = -EINVAL; - dev_warn(dev, "PWM enable %ld not " - "supported. Choose one of 0, 1, or 2.\n", - val); - goto exit; - } - /* Refresh the cache */ - data->pwm_config[ix] = dme1737_read(data, - DME1737_REG_PWM_CONFIG(ix)); - if (val == PWM_EN_FROM_REG(data->pwm_config[ix])) { - /* Bail out if no change */ - goto exit; - } - /* Do some housekeeping if we are currently in auto mode */ - if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { - /* Save the current zone channel assignment */ - data->pwm_acz[ix] = PWM_ACZ_FROM_REG( - data->pwm_config[ix]); - /* Save the current ramp rate state and disable it */ - data->pwm_rr[ix > 0] = dme1737_read(data, - DME1737_REG_PWM_RR(ix > 0)); - data->pwm_rr_en &= ~(1 << ix); - if (PWM_RR_EN_FROM_REG(data->pwm_rr[ix > 0], ix)) { - data->pwm_rr_en |= (1 << ix); - data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(0, ix, - data->pwm_rr[ix > 0]); - dme1737_write(data, - DME1737_REG_PWM_RR(ix > 0), - data->pwm_rr[ix > 0]); - } - } - /* Set the new PWM mode */ - switch (val) { - case 0: - /* Change permissions of pwm[ix] to read-only */ - dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], - S_IRUGO); - /* Turn fan fully on */ - data->pwm_config[ix] = PWM_EN_TO_REG(0, - data->pwm_config[ix]); - dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), - data->pwm_config[ix]); - break; - case 1: - /* Turn on manual mode */ - data->pwm_config[ix] = PWM_EN_TO_REG(1, - data->pwm_config[ix]); - dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), - data->pwm_config[ix]); - /* Change permissions of pwm[ix] to read-writeable */ - dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], - S_IRUGO | S_IWUSR); - break; - case 2: - /* Change permissions of pwm[ix] to read-only */ - dme1737_chmod_file(dev, dme1737_pwm_chmod_attr[ix], - S_IRUGO); - /* - * Turn on auto mode using the saved zone channel - * assignment - */ - data->pwm_config[ix] = PWM_ACZ_TO_REG( - data->pwm_acz[ix], - data->pwm_config[ix]); - dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), - data->pwm_config[ix]); - /* Enable PWM ramp rate if previously enabled */ - if (data->pwm_rr_en & (1 << ix)) { - data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(1, ix, - dme1737_read(data, - DME1737_REG_PWM_RR(ix > 0))); - dme1737_write(data, - DME1737_REG_PWM_RR(ix > 0), - data->pwm_rr[ix > 0]); - } - break; - } - break; - case SYS_PWM_RAMP_RATE: - /* Only valid for pwm[1-3] */ - /* Refresh the cache */ - data->pwm_config[ix] = dme1737_read(data, - DME1737_REG_PWM_CONFIG(ix)); - data->pwm_rr[ix > 0] = dme1737_read(data, - DME1737_REG_PWM_RR(ix > 0)); - /* Set the ramp rate value */ - if (val > 0) { - data->pwm_rr[ix > 0] = PWM_RR_TO_REG(val, ix, - data->pwm_rr[ix > 0]); - } - /* - * Enable/disable the feature only if the associated PWM - * output is in automatic mode. - */ - if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { - data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(val > 0, ix, - data->pwm_rr[ix > 0]); - } - dme1737_write(data, DME1737_REG_PWM_RR(ix > 0), - data->pwm_rr[ix > 0]); - break; - case SYS_PWM_AUTO_CHANNELS_ZONE: - /* Only valid for pwm[1-3] */ - if (!(val == 1 || val == 2 || val == 4 || - val == 6 || val == 7)) { - count = -EINVAL; - dev_warn(dev, "PWM auto channels zone %ld " - "not supported. Choose one of 1, 2, 4, 6, " - "or 7.\n", val); - goto exit; - } - /* Refresh the cache */ - data->pwm_config[ix] = dme1737_read(data, - DME1737_REG_PWM_CONFIG(ix)); - if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) { - /* - * PWM is already in auto mode so update the temp - * channel assignment - */ - data->pwm_config[ix] = PWM_ACZ_TO_REG(val, - data->pwm_config[ix]); - dme1737_write(data, DME1737_REG_PWM_CONFIG(ix), - data->pwm_config[ix]); - } else { - /* - * PWM is not in auto mode so we save the temp - * channel assignment for later use - */ - data->pwm_acz[ix] = val; - } - break; - case SYS_PWM_AUTO_PWM_MIN: - /* Only valid for pwm[1-3] */ - /* Refresh the cache */ - data->pwm_min[ix] = dme1737_read(data, - DME1737_REG_PWM_MIN(ix)); - /* - * There are only 2 values supported for the auto_pwm_min - * value: 0 or auto_point1_pwm. So if the temperature drops - * below the auto_point1_temp_hyst value, the fan either turns - * off or runs at auto_point1_pwm duty-cycle. - */ - if (val > ((data->pwm_min[ix] + 1) / 2)) { - data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix, - dme1737_read(data, - DME1737_REG_PWM_RR(0))); - } else { - data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix, - dme1737_read(data, - DME1737_REG_PWM_RR(0))); - } - dme1737_write(data, DME1737_REG_PWM_RR(0), - data->pwm_rr[0]); - break; - case SYS_PWM_AUTO_POINT1_PWM: - /* Only valid for pwm[1-3] */ - data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255); - dme1737_write(data, DME1737_REG_PWM_MIN(ix), - data->pwm_min[ix]); - break; - default: - dev_dbg(dev, "Unknown function %d.\n", fn); - } -exit: - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Miscellaneous sysfs attributes - * --------------------------------------------------------------------- */ - -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct dme1737_data *data = i2c_get_clientdata(client); - - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} - -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dme1737_update_device(dev); - - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} - -static ssize_t show_name(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} - -/* --------------------------------------------------------------------- - * Sysfs device attribute defines and structs - * --------------------------------------------------------------------- */ - -/* Voltages 0-7 */ - -#define SENSOR_DEVICE_ATTR_IN(ix) \ -static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \ - show_in, NULL, SYS_IN_INPUT, ix); \ -static SENSOR_DEVICE_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \ - show_in, set_in, SYS_IN_MIN, ix); \ -static SENSOR_DEVICE_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \ - show_in, set_in, SYS_IN_MAX, ix); \ -static SENSOR_DEVICE_ATTR_2(in##ix##_alarm, S_IRUGO, \ - show_in, NULL, SYS_IN_ALARM, ix) - -SENSOR_DEVICE_ATTR_IN(0); -SENSOR_DEVICE_ATTR_IN(1); -SENSOR_DEVICE_ATTR_IN(2); -SENSOR_DEVICE_ATTR_IN(3); -SENSOR_DEVICE_ATTR_IN(4); -SENSOR_DEVICE_ATTR_IN(5); -SENSOR_DEVICE_ATTR_IN(6); -SENSOR_DEVICE_ATTR_IN(7); - -/* Temperatures 1-3 */ - -#define SENSOR_DEVICE_ATTR_TEMP(ix) \ -static SENSOR_DEVICE_ATTR_2(temp##ix##_input, S_IRUGO, \ - show_temp, NULL, SYS_TEMP_INPUT, ix-1); \ -static SENSOR_DEVICE_ATTR_2(temp##ix##_min, S_IRUGO | S_IWUSR, \ - show_temp, set_temp, SYS_TEMP_MIN, ix-1); \ -static SENSOR_DEVICE_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \ - show_temp, set_temp, SYS_TEMP_MAX, ix-1); \ -static SENSOR_DEVICE_ATTR_2(temp##ix##_offset, S_IRUGO, \ - show_temp, set_temp, SYS_TEMP_OFFSET, ix-1); \ -static SENSOR_DEVICE_ATTR_2(temp##ix##_alarm, S_IRUGO, \ - show_temp, NULL, SYS_TEMP_ALARM, ix-1); \ -static SENSOR_DEVICE_ATTR_2(temp##ix##_fault, S_IRUGO, \ - show_temp, NULL, SYS_TEMP_FAULT, ix-1) - -SENSOR_DEVICE_ATTR_TEMP(1); -SENSOR_DEVICE_ATTR_TEMP(2); -SENSOR_DEVICE_ATTR_TEMP(3); - -/* Zones 1-3 */ - -#define SENSOR_DEVICE_ATTR_ZONE(ix) \ -static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_channels_temp, S_IRUGO, \ - show_zone, NULL, SYS_ZONE_AUTO_CHANNELS_TEMP, ix-1); \ -static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point1_temp_hyst, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP_HYST, ix-1); \ -static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point1_temp, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP, ix-1); \ -static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point2_temp, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT2_TEMP, ix-1); \ -static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point3_temp, S_IRUGO, \ - show_zone, set_zone, SYS_ZONE_AUTO_POINT3_TEMP, ix-1) - -SENSOR_DEVICE_ATTR_ZONE(1); -SENSOR_DEVICE_ATTR_ZONE(2); -SENSOR_DEVICE_ATTR_ZONE(3); - -/* Fans 1-4 */ - -#define SENSOR_DEVICE_ATTR_FAN_1TO4(ix) \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_input, S_IRUGO, \ - show_fan, NULL, SYS_FAN_INPUT, ix-1); \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_MIN, ix-1); \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_alarm, S_IRUGO, \ - show_fan, NULL, SYS_FAN_ALARM, ix-1); \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_type, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_TYPE, ix-1) - -SENSOR_DEVICE_ATTR_FAN_1TO4(1); -SENSOR_DEVICE_ATTR_FAN_1TO4(2); -SENSOR_DEVICE_ATTR_FAN_1TO4(3); -SENSOR_DEVICE_ATTR_FAN_1TO4(4); - -/* Fans 5-6 */ - -#define SENSOR_DEVICE_ATTR_FAN_5TO6(ix) \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_input, S_IRUGO, \ - show_fan, NULL, SYS_FAN_INPUT, ix-1); \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_MIN, ix-1); \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_alarm, S_IRUGO, \ - show_fan, NULL, SYS_FAN_ALARM, ix-1); \ -static SENSOR_DEVICE_ATTR_2(fan##ix##_max, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SYS_FAN_MAX, ix-1) - -SENSOR_DEVICE_ATTR_FAN_5TO6(5); -SENSOR_DEVICE_ATTR_FAN_5TO6(6); - -/* PWMs 1-3 */ - -#define SENSOR_DEVICE_ATTR_PWM_1TO3(ix) \ -static SENSOR_DEVICE_ATTR_2(pwm##ix, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_freq, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_enable, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_ENABLE, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_ramp_rate, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_RAMP_RATE, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_channels_zone, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_AUTO_CHANNELS_ZONE, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_pwm_min, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_AUTO_PWM_MIN, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_point1_pwm, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_AUTO_POINT1_PWM, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_point2_pwm, S_IRUGO, \ - show_pwm, NULL, SYS_PWM_AUTO_POINT2_PWM, ix-1) - -SENSOR_DEVICE_ATTR_PWM_1TO3(1); -SENSOR_DEVICE_ATTR_PWM_1TO3(2); -SENSOR_DEVICE_ATTR_PWM_1TO3(3); - -/* PWMs 5-6 */ - -#define SENSOR_DEVICE_ATTR_PWM_5TO6(ix) \ -static SENSOR_DEVICE_ATTR_2(pwm##ix, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_freq, S_IRUGO, \ - show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \ -static SENSOR_DEVICE_ATTR_2(pwm##ix##_enable, S_IRUGO, \ - show_pwm, NULL, SYS_PWM_ENABLE, ix-1) - -SENSOR_DEVICE_ATTR_PWM_5TO6(5); -SENSOR_DEVICE_ATTR_PWM_5TO6(6); - -/* Misc */ - -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); /* for ISA devices */ - -/* - * This struct holds all the attributes that are always present and need to be - * created unconditionally. The attributes that need modification of their - * permissions are created read-only and write permissions are added or removed - * on the fly when required - */ -static struct attribute *dme1737_attr[] = { - /* Voltages */ - &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, - &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, - &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, - &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, - &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, - &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, - &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, - /* Temperatures */ - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - /* Zones */ - &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_zone1_auto_channels_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_channels_temp.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_group = { - .attrs = dme1737_attr, -}; - -/* - * The following struct holds temp offset attributes, which are not available - * in all chips. The following chips support them: - * DME1737, SCH311x - */ -static struct attribute *dme1737_temp_offset_attr[] = { - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_temp_offset_group = { - .attrs = dme1737_temp_offset_attr, -}; - -/* - * The following struct holds VID related attributes, which are not available - * in all chips. The following chips support them: - * DME1737 - */ -static struct attribute *dme1737_vid_attr[] = { - &dev_attr_vrm.attr, - &dev_attr_cpu0_vid.attr, - NULL -}; - -static const struct attribute_group dme1737_vid_group = { - .attrs = dme1737_vid_attr, -}; - -/* - * The following struct holds temp zone 3 related attributes, which are not - * available in all chips. The following chips support them: - * DME1737, SCH311x, SCH5027 - */ -static struct attribute *dme1737_zone3_attr[] = { - &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_channels_temp.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_zone3_group = { - .attrs = dme1737_zone3_attr, -}; - - -/* - * The following struct holds temp zone hysteresis related attributes, which - * are not available in all chips. The following chips support them: - * DME1737, SCH311x - */ -static struct attribute *dme1737_zone_hyst_attr[] = { - &sensor_dev_attr_zone1_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point1_temp_hyst.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_zone_hyst_group = { - .attrs = dme1737_zone_hyst_attr, -}; - -/* - * The following struct holds voltage in7 related attributes, which - * are not available in all chips. The following chips support them: - * SCH5127 - */ -static struct attribute *dme1737_in7_attr[] = { - &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 -}; - -static const struct attribute_group dme1737_in7_group = { - .attrs = dme1737_in7_attr, -}; - -/* - * The following structs hold the PWM attributes, some of which are optional. - * Their creation depends on the chip configuration which is determined during - * module load. - */ -static struct attribute *dme1737_pwm1_attr[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm2_attr[] = { - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm3_attr[] = { - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm5_attr[] = { - &sensor_dev_attr_pwm5.dev_attr.attr, - &sensor_dev_attr_pwm5_freq.dev_attr.attr, - &sensor_dev_attr_pwm5_enable.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm6_attr[] = { - &sensor_dev_attr_pwm6.dev_attr.attr, - &sensor_dev_attr_pwm6_freq.dev_attr.attr, - &sensor_dev_attr_pwm6_enable.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_pwm_group[] = { - { .attrs = dme1737_pwm1_attr }, - { .attrs = dme1737_pwm2_attr }, - { .attrs = dme1737_pwm3_attr }, - { .attrs = NULL }, - { .attrs = dme1737_pwm5_attr }, - { .attrs = dme1737_pwm6_attr }, -}; - -/* - * The following struct holds auto PWM min attributes, which are not available - * in all chips. Their creation depends on the chip type which is determined - * during module load. - */ -static struct attribute *dme1737_auto_pwm_min_attr[] = { - &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, -}; - -/* - * The following structs hold the fan attributes, some of which are optional. - * Their creation depends on the chip configuration which is determined during - * module load. - */ -static struct attribute *dme1737_fan1_attr[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_type.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_fan2_attr[] = { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_type.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_fan3_attr[] = { - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_type.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_fan4_attr[] = { - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - &sensor_dev_attr_fan4_type.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_fan5_attr[] = { - &sensor_dev_attr_fan5_input.dev_attr.attr, - &sensor_dev_attr_fan5_min.dev_attr.attr, - &sensor_dev_attr_fan5_alarm.dev_attr.attr, - &sensor_dev_attr_fan5_max.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_fan6_attr[] = { - &sensor_dev_attr_fan6_input.dev_attr.attr, - &sensor_dev_attr_fan6_min.dev_attr.attr, - &sensor_dev_attr_fan6_alarm.dev_attr.attr, - &sensor_dev_attr_fan6_max.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_fan_group[] = { - { .attrs = dme1737_fan1_attr }, - { .attrs = dme1737_fan2_attr }, - { .attrs = dme1737_fan3_attr }, - { .attrs = dme1737_fan4_attr }, - { .attrs = dme1737_fan5_attr }, - { .attrs = dme1737_fan6_attr }, -}; - -/* - * The permissions of the following zone attributes are changed to read- - * writeable if the chip is *not* locked. Otherwise they stay read-only. - */ -static struct attribute *dme1737_zone_chmod_attr[] = { - &sensor_dev_attr_zone1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_zone1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_zone1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_zone2_auto_point3_temp.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_zone_chmod_group = { - .attrs = dme1737_zone_chmod_attr, -}; - - -/* - * The permissions of the following zone 3 attributes are changed to read- - * writeable if the chip is *not* locked. Otherwise they stay read-only. - */ -static struct attribute *dme1737_zone3_chmod_attr[] = { - &sensor_dev_attr_zone3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_zone3_auto_point3_temp.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_zone3_chmod_group = { - .attrs = dme1737_zone3_chmod_attr, -}; - -/* - * The permissions of the following PWM attributes are changed to read- - * writeable if the chip is *not* locked and the respective PWM is available. - * Otherwise they stay read-only. - */ -static struct attribute *dme1737_pwm1_chmod_attr[] = { - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_ramp_rate.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm2_chmod_attr[] = { - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_ramp_rate.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm3_chmod_attr[] = { - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_ramp_rate.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels_zone.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm5_chmod_attr[] = { - &sensor_dev_attr_pwm5.dev_attr.attr, - &sensor_dev_attr_pwm5_freq.dev_attr.attr, - NULL -}; -static struct attribute *dme1737_pwm6_chmod_attr[] = { - &sensor_dev_attr_pwm6.dev_attr.attr, - &sensor_dev_attr_pwm6_freq.dev_attr.attr, - NULL -}; - -static const struct attribute_group dme1737_pwm_chmod_group[] = { - { .attrs = dme1737_pwm1_chmod_attr }, - { .attrs = dme1737_pwm2_chmod_attr }, - { .attrs = dme1737_pwm3_chmod_attr }, - { .attrs = NULL }, - { .attrs = dme1737_pwm5_chmod_attr }, - { .attrs = dme1737_pwm6_chmod_attr }, -}; - -/* - * Pwm[1-3] are read-writeable if the associated pwm is in manual mode and the - * chip is not locked. Otherwise they are read-only. - */ -static struct attribute *dme1737_pwm_chmod_attr[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, -}; - -/* --------------------------------------------------------------------- - * Super-IO functions - * --------------------------------------------------------------------- */ - -static inline void dme1737_sio_enter(int sio_cip) -{ - outb(0x55, sio_cip); -} - -static inline void dme1737_sio_exit(int sio_cip) -{ - outb(0xaa, sio_cip); -} - -static inline int dme1737_sio_inb(int sio_cip, int reg) -{ - outb(reg, sio_cip); - return inb(sio_cip + 1); -} - -static inline void dme1737_sio_outb(int sio_cip, int reg, int val) -{ - outb(reg, sio_cip); - outb(val, sio_cip + 1); -} - -/* --------------------------------------------------------------------- - * Device initialization - * --------------------------------------------------------------------- */ - -static int dme1737_i2c_get_features(int, struct dme1737_data*); - -static void dme1737_chmod_file(struct device *dev, - struct attribute *attr, umode_t mode) -{ - if (sysfs_chmod_file(&dev->kobj, attr, mode)) { - dev_warn(dev, "Failed to change permissions of %s.\n", - attr->name); - } -} - -static void dme1737_chmod_group(struct device *dev, - const struct attribute_group *group, - umode_t mode) -{ - struct attribute **attr; - - for (attr = group->attrs; *attr; attr++) - dme1737_chmod_file(dev, *attr, mode); -} - -static void dme1737_remove_files(struct device *dev) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - int ix; - - for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { - if (data->has_features & HAS_FAN(ix)) { - sysfs_remove_group(&dev->kobj, - &dme1737_fan_group[ix]); - } - } - - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { - if (data->has_features & HAS_PWM(ix)) { - sysfs_remove_group(&dev->kobj, - &dme1737_pwm_group[ix]); - if ((data->has_features & HAS_PWM_MIN) && ix < 3) { - sysfs_remove_file(&dev->kobj, - dme1737_auto_pwm_min_attr[ix]); - } - } - } - - if (data->has_features & HAS_TEMP_OFFSET) - sysfs_remove_group(&dev->kobj, &dme1737_temp_offset_group); - if (data->has_features & HAS_VID) - sysfs_remove_group(&dev->kobj, &dme1737_vid_group); - if (data->has_features & HAS_ZONE3) - sysfs_remove_group(&dev->kobj, &dme1737_zone3_group); - if (data->has_features & HAS_ZONE_HYST) - sysfs_remove_group(&dev->kobj, &dme1737_zone_hyst_group); - if (data->has_features & HAS_IN7) - sysfs_remove_group(&dev->kobj, &dme1737_in7_group); - sysfs_remove_group(&dev->kobj, &dme1737_group); - - if (!data->client) - sysfs_remove_file(&dev->kobj, &dev_attr_name.attr); -} - -static int dme1737_create_files(struct device *dev) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - int err, ix; - - /* Create a name attribute for ISA devices */ - if (!data->client) { - err = sysfs_create_file(&dev->kobj, &dev_attr_name.attr); - if (err) - goto exit; - } - - /* Create standard sysfs attributes */ - err = sysfs_create_group(&dev->kobj, &dme1737_group); - if (err) - goto exit_remove; - - /* Create chip-dependent sysfs attributes */ - if (data->has_features & HAS_TEMP_OFFSET) { - err = sysfs_create_group(&dev->kobj, - &dme1737_temp_offset_group); - if (err) - goto exit_remove; - } - if (data->has_features & HAS_VID) { - err = sysfs_create_group(&dev->kobj, &dme1737_vid_group); - if (err) - goto exit_remove; - } - if (data->has_features & HAS_ZONE3) { - err = sysfs_create_group(&dev->kobj, &dme1737_zone3_group); - if (err) - goto exit_remove; - } - if (data->has_features & HAS_ZONE_HYST) { - err = sysfs_create_group(&dev->kobj, &dme1737_zone_hyst_group); - if (err) - goto exit_remove; - } - if (data->has_features & HAS_IN7) { - err = sysfs_create_group(&dev->kobj, &dme1737_in7_group); - if (err) - goto exit_remove; - } - - /* Create fan sysfs attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) { - if (data->has_features & HAS_FAN(ix)) { - err = sysfs_create_group(&dev->kobj, - &dme1737_fan_group[ix]); - if (err) - goto exit_remove; - } - } - - /* Create PWM sysfs attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) { - if (data->has_features & HAS_PWM(ix)) { - err = sysfs_create_group(&dev->kobj, - &dme1737_pwm_group[ix]); - if (err) - goto exit_remove; - if ((data->has_features & HAS_PWM_MIN) && (ix < 3)) { - err = sysfs_create_file(&dev->kobj, - dme1737_auto_pwm_min_attr[ix]); - if (err) - goto exit_remove; - } - } - } - - /* - * Inform if the device is locked. Otherwise change the permissions of - * selected attributes from read-only to read-writeable. - */ - if (data->config & 0x02) { - dev_info(dev, "Device is locked. Some attributes " - "will be read-only.\n"); - } else { - /* Change permissions of zone sysfs attributes */ - dme1737_chmod_group(dev, &dme1737_zone_chmod_group, - S_IRUGO | S_IWUSR); - - /* Change permissions of chip-dependent sysfs attributes */ - if (data->has_features & HAS_TEMP_OFFSET) { - dme1737_chmod_group(dev, &dme1737_temp_offset_group, - S_IRUGO | S_IWUSR); - } - if (data->has_features & HAS_ZONE3) { - dme1737_chmod_group(dev, &dme1737_zone3_chmod_group, - S_IRUGO | S_IWUSR); - } - if (data->has_features & HAS_ZONE_HYST) { - dme1737_chmod_group(dev, &dme1737_zone_hyst_group, - S_IRUGO | S_IWUSR); - } - - /* Change permissions of PWM sysfs attributes */ - for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_chmod_group); ix++) { - if (data->has_features & HAS_PWM(ix)) { - dme1737_chmod_group(dev, - &dme1737_pwm_chmod_group[ix], - S_IRUGO | S_IWUSR); - if ((data->has_features & HAS_PWM_MIN) && - ix < 3) { - dme1737_chmod_file(dev, - dme1737_auto_pwm_min_attr[ix], - S_IRUGO | S_IWUSR); - } - } - } - - /* Change permissions of pwm[1-3] if in manual mode */ - for (ix = 0; ix < 3; ix++) { - if ((data->has_features & HAS_PWM(ix)) && - (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) { - dme1737_chmod_file(dev, - dme1737_pwm_chmod_attr[ix], - S_IRUGO | S_IWUSR); - } - } - } - - return 0; - -exit_remove: - dme1737_remove_files(dev); -exit: - return err; -} - -static int dme1737_init_device(struct device *dev) -{ - struct dme1737_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - int ix; - u8 reg; - - /* Point to the right nominal voltages array */ - data->in_nominal = IN_NOMINAL(data->type); - - data->config = dme1737_read(data, DME1737_REG_CONFIG); - /* Inform if part is not monitoring/started */ - if (!(data->config & 0x01)) { - if (!force_start) { - dev_err(dev, "Device is not monitoring. " - "Use the force_start load parameter to " - "override.\n"); - return -EFAULT; - } - - /* Force monitoring */ - data->config |= 0x01; - dme1737_write(data, DME1737_REG_CONFIG, data->config); - } - /* Inform if part is not ready */ - if (!(data->config & 0x04)) { - dev_err(dev, "Device is not ready.\n"); - return -EFAULT; - } - - /* - * Determine which optional fan and pwm features are enabled (only - * valid for I2C devices) - */ - if (client) { /* I2C chip */ - data->config2 = dme1737_read(data, DME1737_REG_CONFIG2); - /* Check if optional fan3 input is enabled */ - if (data->config2 & 0x04) - data->has_features |= HAS_FAN(2); - - /* - * Fan4 and pwm3 are only available if the client's I2C address - * is the default 0x2e. Otherwise the I/Os associated with - * these functions are used for addr enable/select. - */ - if (client->addr == 0x2e) - data->has_features |= HAS_FAN(3) | HAS_PWM(2); - - /* - * Determine which of the optional fan[5-6] and pwm[5-6] - * features are enabled. For this, we need to query the runtime - * registers through the Super-IO LPC interface. Try both - * config ports 0x2e and 0x4e. - */ - if (dme1737_i2c_get_features(0x2e, data) && - dme1737_i2c_get_features(0x4e, data)) { - dev_warn(dev, "Failed to query Super-IO for optional " - "features.\n"); - } - } - - /* Fan[1-2] and pwm[1-2] are present in all chips */ - data->has_features |= HAS_FAN(0) | HAS_FAN(1) | HAS_PWM(0) | HAS_PWM(1); - - /* Chip-dependent features */ - switch (data->type) { - case dme1737: - data->has_features |= HAS_TEMP_OFFSET | HAS_VID | HAS_ZONE3 | - HAS_ZONE_HYST | HAS_PWM_MIN; - break; - case sch311x: - data->has_features |= HAS_TEMP_OFFSET | HAS_ZONE3 | - HAS_ZONE_HYST | HAS_PWM_MIN | HAS_FAN(2) | HAS_PWM(2); - break; - case sch5027: - data->has_features |= HAS_ZONE3; - break; - case sch5127: - data->has_features |= HAS_FAN(2) | HAS_PWM(2) | HAS_IN7; - break; - default: - break; - } - - dev_info(dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, " - "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n", - (data->has_features & HAS_PWM(2)) ? "yes" : "no", - (data->has_features & HAS_PWM(4)) ? "yes" : "no", - (data->has_features & HAS_PWM(5)) ? "yes" : "no", - (data->has_features & HAS_FAN(2)) ? "yes" : "no", - (data->has_features & HAS_FAN(3)) ? "yes" : "no", - (data->has_features & HAS_FAN(4)) ? "yes" : "no", - (data->has_features & HAS_FAN(5)) ? "yes" : "no"); - - reg = dme1737_read(data, DME1737_REG_TACH_PWM); - /* Inform if fan-to-pwm mapping differs from the default */ - if (client && reg != 0xa4) { /* I2C chip */ - dev_warn(dev, "Non-standard fan to pwm mapping: " - "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, " - "fan4->pwm%d. Please report to the driver " - "maintainer.\n", - (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, - ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1); - } else if (!client && reg != 0x24) { /* ISA chip */ - dev_warn(dev, "Non-standard fan to pwm mapping: " - "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d. " - "Please report to the driver maintainer.\n", - (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1, - ((reg >> 4) & 0x03) + 1); - } - - /* - * Switch pwm[1-3] to manual mode if they are currently disabled and - * set the duty-cycles to 0% (which is identical to the PWMs being - * disabled). - */ - if (!(data->config & 0x02)) { - for (ix = 0; ix < 3; ix++) { - data->pwm_config[ix] = dme1737_read(data, - DME1737_REG_PWM_CONFIG(ix)); - if ((data->has_features & HAS_PWM(ix)) && - (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) { - dev_info(dev, "Switching pwm%d to " - "manual mode.\n", ix + 1); - data->pwm_config[ix] = PWM_EN_TO_REG(1, - data->pwm_config[ix]); - dme1737_write(data, DME1737_REG_PWM(ix), 0); - dme1737_write(data, - DME1737_REG_PWM_CONFIG(ix), - data->pwm_config[ix]); - } - } - } - - /* Initialize the default PWM auto channels zone (acz) assignments */ - data->pwm_acz[0] = 1; /* pwm1 -> zone1 */ - data->pwm_acz[1] = 2; /* pwm2 -> zone2 */ - data->pwm_acz[2] = 4; /* pwm3 -> zone3 */ - - /* Set VRM */ - if (data->has_features & HAS_VID) - data->vrm = vid_which_vrm(); - - return 0; -} - -/* --------------------------------------------------------------------- - * I2C device detection and registration - * --------------------------------------------------------------------- */ - -static struct i2c_driver dme1737_i2c_driver; - -static int dme1737_i2c_get_features(int sio_cip, struct dme1737_data *data) -{ - int err = 0, reg; - u16 addr; - - dme1737_sio_enter(sio_cip); - - /* - * Check device ID - * We currently know about two kinds of DME1737 and SCH5027. - */ - reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); - if (!(reg == DME1737_ID_1 || reg == DME1737_ID_2 || - reg == SCH5027_ID)) { - err = -ENODEV; - goto exit; - } - - /* Select logical device A (runtime registers) */ - dme1737_sio_outb(sio_cip, 0x07, 0x0a); - - /* Get the base address of the runtime registers */ - addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | - dme1737_sio_inb(sio_cip, 0x61); - if (!addr) { - err = -ENODEV; - goto exit; - } - - /* - * Read the runtime registers to determine which optional features - * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set - * to '10' if the respective feature is enabled. - */ - if ((inb(addr + 0x43) & 0x0c) == 0x08) /* fan6 */ - data->has_features |= HAS_FAN(5); - if ((inb(addr + 0x44) & 0x0c) == 0x08) /* pwm6 */ - data->has_features |= HAS_PWM(5); - if ((inb(addr + 0x45) & 0x0c) == 0x08) /* fan5 */ - data->has_features |= HAS_FAN(4); - if ((inb(addr + 0x46) & 0x0c) == 0x08) /* pwm5 */ - data->has_features |= HAS_PWM(4); - -exit: - dme1737_sio_exit(sio_cip); - - return err; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int dme1737_i2c_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - struct device *dev = &adapter->dev; - u8 company, verstep = 0; - const char *name; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - company = i2c_smbus_read_byte_data(client, DME1737_REG_COMPANY); - verstep = i2c_smbus_read_byte_data(client, DME1737_REG_VERSTEP); - - if (company == DME1737_COMPANY_SMSC && - verstep == SCH5027_VERSTEP) { - name = "sch5027"; - } else if (company == DME1737_COMPANY_SMSC && - (verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP) { - name = "dme1737"; - } else { - return -ENODEV; - } - - dev_info(dev, "Found a %s chip at 0x%02x (rev 0x%02x).\n", - verstep == SCH5027_VERSTEP ? "SCH5027" : "DME1737", - client->addr, verstep); - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int dme1737_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct dme1737_data *data; - struct device *dev = &client->dev; - int err; - - data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - data->client = client; - data->name = client->name; - mutex_init(&data->update_lock); - - /* Initialize the DME1737 chip */ - err = dme1737_init_device(dev); - if (err) { - dev_err(dev, "Failed to initialize device.\n"); - goto exit_kfree; - } - - /* Create sysfs files */ - err = dme1737_create_files(dev); - if (err) { - dev_err(dev, "Failed to create sysfs files.\n"); - goto exit_kfree; - } - - /* Register device */ - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - dev_err(dev, "Failed to register device.\n"); - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - dme1737_remove_files(dev); -exit_kfree: - kfree(data); -exit: - return err; -} - -static int dme1737_i2c_remove(struct i2c_client *client) -{ - struct dme1737_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - dme1737_remove_files(&client->dev); - - kfree(data); - return 0; -} - -static const struct i2c_device_id dme1737_id[] = { - { "dme1737", dme1737 }, - { "sch5027", sch5027 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, dme1737_id); - -static struct i2c_driver dme1737_i2c_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "dme1737", - }, - .probe = dme1737_i2c_probe, - .remove = dme1737_i2c_remove, - .id_table = dme1737_id, - .detect = dme1737_i2c_detect, - .address_list = normal_i2c, -}; - -/* --------------------------------------------------------------------- - * ISA device detection and registration - * --------------------------------------------------------------------- */ - -static int __init dme1737_isa_detect(int sio_cip, unsigned short *addr) -{ - int err = 0, reg; - unsigned short base_addr; - - dme1737_sio_enter(sio_cip); - - /* - * Check device ID - * We currently know about SCH3112, SCH3114, SCH3116, and SCH5127 - */ - reg = force_id ? force_id : dme1737_sio_inb(sio_cip, 0x20); - if (!(reg == SCH3112_ID || reg == SCH3114_ID || reg == SCH3116_ID || - reg == SCH5127_ID)) { - err = -ENODEV; - goto exit; - } - - /* Select logical device A (runtime registers) */ - dme1737_sio_outb(sio_cip, 0x07, 0x0a); - - /* Get the base address of the runtime registers */ - base_addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) | - dme1737_sio_inb(sio_cip, 0x61); - if (!base_addr) { - pr_err("Base address not set\n"); - err = -ENODEV; - goto exit; - } - - /* - * Access to the hwmon registers is through an index/data register - * pair located at offset 0x70/0x71. - */ - *addr = base_addr + 0x70; - -exit: - dme1737_sio_exit(sio_cip); - return err; -} - -static int __init dme1737_isa_device_add(unsigned short addr) -{ - struct resource res = { - .start = addr, - .end = addr + DME1737_EXTENT - 1, - .name = "dme1737", - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc("dme1737", addr); - if (!pdev) { - pr_err("Failed to allocate device\n"); - err = -ENOMEM; - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Failed to add device resource (err = %d)\n", err); - goto exit_device_put; - } - - err = platform_device_add(pdev); - if (err) { - pr_err("Failed to add device (err = %d)\n", err); - goto exit_device_put; - } - - return 0; - -exit_device_put: - platform_device_put(pdev); - pdev = NULL; -exit: - return err; -} - -static int __devinit dme1737_isa_probe(struct platform_device *pdev) -{ - u8 company, device; - struct resource *res; - struct dme1737_data *data; - struct device *dev = &pdev->dev; - int err; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, DME1737_EXTENT, "dme1737")) { - dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", - (unsigned short)res->start, - (unsigned short)res->start + DME1737_EXTENT - 1); - err = -EBUSY; - goto exit; - } - - data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release_region; - } - - data->addr = res->start; - platform_set_drvdata(pdev, data); - - /* Skip chip detection if module is loaded with force_id parameter */ - switch (force_id) { - case SCH3112_ID: - case SCH3114_ID: - case SCH3116_ID: - data->type = sch311x; - break; - case SCH5127_ID: - data->type = sch5127; - break; - default: - company = dme1737_read(data, DME1737_REG_COMPANY); - device = dme1737_read(data, DME1737_REG_DEVICE); - - if ((company == DME1737_COMPANY_SMSC) && - (device == SCH311X_DEVICE)) { - data->type = sch311x; - } else if ((company == DME1737_COMPANY_SMSC) && - (device == SCH5127_DEVICE)) { - data->type = sch5127; - } else { - err = -ENODEV; - goto exit_kfree; - } - } - - if (data->type == sch5127) - data->name = "sch5127"; - else - data->name = "sch311x"; - - /* Initialize the mutex */ - mutex_init(&data->update_lock); - - dev_info(dev, "Found a %s chip at 0x%04x\n", - data->type == sch5127 ? "SCH5127" : "SCH311x", data->addr); - - /* Initialize the chip */ - err = dme1737_init_device(dev); - if (err) { - dev_err(dev, "Failed to initialize device.\n"); - goto exit_kfree; - } - - /* Create sysfs files */ - err = dme1737_create_files(dev); - if (err) { - dev_err(dev, "Failed to create sysfs files.\n"); - goto exit_kfree; - } - - /* Register device */ - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - dev_err(dev, "Failed to register device.\n"); - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - dme1737_remove_files(dev); -exit_kfree: - platform_set_drvdata(pdev, NULL); - kfree(data); -exit_release_region: - release_region(res->start, DME1737_EXTENT); -exit: - return err; -} - -static int __devexit dme1737_isa_remove(struct platform_device *pdev) -{ - struct dme1737_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - dme1737_remove_files(&pdev->dev); - release_region(data->addr, DME1737_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static struct platform_driver dme1737_isa_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "dme1737", - }, - .probe = dme1737_isa_probe, - .remove = __devexit_p(dme1737_isa_remove), -}; - -/* --------------------------------------------------------------------- - * Module initialization and cleanup - * --------------------------------------------------------------------- */ - -static int __init dme1737_init(void) -{ - int err; - unsigned short addr; - - err = i2c_add_driver(&dme1737_i2c_driver); - if (err) - goto exit; - - if (dme1737_isa_detect(0x2e, &addr) && - dme1737_isa_detect(0x4e, &addr) && - (!probe_all_addr || - (dme1737_isa_detect(0x162e, &addr) && - dme1737_isa_detect(0x164e, &addr)))) { - /* Return 0 if we didn't find an ISA device */ - return 0; - } - - err = platform_driver_register(&dme1737_isa_driver); - if (err) - goto exit_del_i2c_driver; - - /* Sets global pdev as a side effect */ - err = dme1737_isa_device_add(addr); - if (err) - goto exit_del_isa_driver; - - return 0; - -exit_del_isa_driver: - platform_driver_unregister(&dme1737_isa_driver); -exit_del_i2c_driver: - i2c_del_driver(&dme1737_i2c_driver); -exit: - return err; -} - -static void __exit dme1737_exit(void) -{ - if (pdev) { - platform_device_unregister(pdev); - platform_driver_unregister(&dme1737_isa_driver); - } - - i2c_del_driver(&dme1737_i2c_driver); -} - -MODULE_AUTHOR("Juerg Haefliger "); -MODULE_DESCRIPTION("DME1737 sensors"); -MODULE_LICENSE("GPL"); - -module_init(dme1737_init); -module_exit(dme1737_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/ds1621.c b/ANDROID_3.4.5/drivers/hwmon/ds1621.c deleted file mode 100644 index f647a330..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ds1621.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * ds1621.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Christian W. Zuckschwerdt 2000-11-23 - * based on lm75.c by Frodo Looijaard - * Ported to Linux 2.6 by Aurelien Jarno with - * the help of Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lm75.h" - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, - 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; - -/* Insmod parameters */ -static int polarity = -1; -module_param(polarity, int, 0); -MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low"); - -/* Many DS1621 constants specified below */ -/* Config register used for detection */ -/* 7 6 5 4 3 2 1 0 */ -/* |Done|THF |TLF |NVB | X | X |POL |1SHOT| */ -#define DS1621_REG_CONFIG_NVB 0x10 -#define DS1621_REG_CONFIG_POLARITY 0x02 -#define DS1621_REG_CONFIG_1SHOT 0x01 -#define DS1621_REG_CONFIG_DONE 0x80 - -/* The DS1621 registers */ -static const u8 DS1621_REG_TEMP[3] = { - 0xAA, /* input, word, RO */ - 0xA2, /* min, word, RW */ - 0xA1, /* max, word, RW */ -}; -#define DS1621_REG_CONF 0xAC /* byte, RW */ -#define DS1621_COM_START 0xEE /* no data */ -#define DS1621_COM_STOP 0x22 /* no data */ - -/* The DS1621 configuration register */ -#define DS1621_ALARM_TEMP_HIGH 0x40 -#define DS1621_ALARM_TEMP_LOW 0x20 - -/* Conversions */ -#define ALARMS_FROM_REG(val) ((val) & \ - (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW)) - -/* Each client has this additional data */ -struct ds1621_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u16 temp[3]; /* Register values, word */ - u8 conf; /* Register encoding, combined */ -}; - -static void ds1621_init_client(struct i2c_client *client) -{ - u8 conf, new_conf; - - new_conf = conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); - /* switch to continuous conversion mode */ - new_conf &= ~DS1621_REG_CONFIG_1SHOT; - - /* setup output polarity */ - if (polarity == 0) - new_conf &= ~DS1621_REG_CONFIG_POLARITY; - else if (polarity == 1) - new_conf |= DS1621_REG_CONFIG_POLARITY; - - if (conf != new_conf) - i2c_smbus_write_byte_data(client, DS1621_REG_CONF, new_conf); - - /* start conversion */ - i2c_smbus_write_byte(client, DS1621_COM_START); -} - -static struct ds1621_data *ds1621_update_client(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ds1621_data *data = i2c_get_clientdata(client); - u8 new_conf; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - - dev_dbg(&client->dev, "Starting ds1621 update\n"); - - data->conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); - - for (i = 0; i < ARRAY_SIZE(data->temp); i++) - data->temp[i] = i2c_smbus_read_word_swapped(client, - DS1621_REG_TEMP[i]); - - /* reset alarms if necessary */ - new_conf = data->conf; - if (data->temp[0] > data->temp[1]) /* input > min */ - new_conf &= ~DS1621_ALARM_TEMP_LOW; - if (data->temp[0] < data->temp[2]) /* input < max */ - new_conf &= ~DS1621_ALARM_TEMP_HIGH; - if (data->conf != new_conf) - i2c_smbus_write_byte_data(client, DS1621_REG_CONF, - new_conf); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ds1621_data *data = ds1621_update_client(dev); - return sprintf(buf, "%d\n", - LM75_TEMP_FROM_REG(data->temp[attr->index])); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct ds1621_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp[attr->index] = LM75_TEMP_TO_REG(val); - i2c_smbus_write_word_swapped(client, DS1621_REG_TEMP[attr->index], - data->temp[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarms(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct ds1621_data *data = ds1621_update_client(dev); - return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf)); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ds1621_data *data = ds1621_update_client(dev); - return sprintf(buf, "%d\n", !!(data->conf & attr->index)); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, - DS1621_ALARM_TEMP_LOW); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, - DS1621_ALARM_TEMP_HIGH); - -static struct attribute *ds1621_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - NULL -}; - -static const struct attribute_group ds1621_group = { - .attrs = ds1621_attributes, -}; - - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int ds1621_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int conf, temp; - int i; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_WORD_DATA - | I2C_FUNC_SMBUS_WRITE_BYTE)) - return -ENODEV; - - /* - * Now, we do the remaining detection. It is lousy. - * - * The NVB bit should be low if no EEPROM write has been requested - * during the latest 10ms, which is highly improbable in our case. - */ - conf = i2c_smbus_read_byte_data(client, DS1621_REG_CONF); - if (conf < 0 || conf & DS1621_REG_CONFIG_NVB) - return -ENODEV; - /* The 7 lowest bits of a temperature should always be 0. */ - for (i = 0; i < ARRAY_SIZE(DS1621_REG_TEMP); i++) { - temp = i2c_smbus_read_word_data(client, DS1621_REG_TEMP[i]); - if (temp < 0 || (temp & 0x7f00)) - return -ENODEV; - } - - strlcpy(info->type, "ds1621", I2C_NAME_SIZE); - - return 0; -} - -static int ds1621_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ds1621_data *data; - int err; - - data = kzalloc(sizeof(struct ds1621_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the DS1621 chip */ - ds1621_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &ds1621_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - - exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &ds1621_group); - exit_free: - kfree(data); - exit: - return err; -} - -static int ds1621_remove(struct i2c_client *client) -{ - struct ds1621_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ds1621_group); - - kfree(data); - - return 0; -} - -static const struct i2c_device_id ds1621_id[] = { - { "ds1621", 0 }, - { "ds1625", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ds1621_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ds1621_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "ds1621", - }, - .probe = ds1621_probe, - .remove = ds1621_remove, - .id_table = ds1621_id, - .detect = ds1621_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(ds1621_driver); - -MODULE_AUTHOR("Christian W. Zuckschwerdt "); -MODULE_DESCRIPTION("DS1621 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ds620.c b/ANDROID_3.4.5/drivers/hwmon/ds620.c deleted file mode 100644 index 50663efa..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ds620.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * ds620.c - Support for temperature sensor and thermostat DS620 - * - * Copyright (C) 2010, 2011 Roland Stigge - * - * based on ds1621.c by Christian W. Zuckschwerdt - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Many DS620 constants specified below - * 15 14 13 12 11 10 09 08 - * |Done|NVB |THF |TLF |R1 |R0 |AUTOC|1SHOT| - * - * 07 06 05 04 03 02 01 00 - * |PO2 |PO1 |A2 |A1 |A0 | | | | - */ -#define DS620_REG_CONFIG_DONE 0x8000 -#define DS620_REG_CONFIG_NVB 0x4000 -#define DS620_REG_CONFIG_THF 0x2000 -#define DS620_REG_CONFIG_TLF 0x1000 -#define DS620_REG_CONFIG_R1 0x0800 -#define DS620_REG_CONFIG_R0 0x0400 -#define DS620_REG_CONFIG_AUTOC 0x0200 -#define DS620_REG_CONFIG_1SHOT 0x0100 -#define DS620_REG_CONFIG_PO2 0x0080 -#define DS620_REG_CONFIG_PO1 0x0040 -#define DS620_REG_CONFIG_A2 0x0020 -#define DS620_REG_CONFIG_A1 0x0010 -#define DS620_REG_CONFIG_A0 0x0008 - -/* The DS620 registers */ -static const u8 DS620_REG_TEMP[3] = { - 0xAA, /* input, word, RO */ - 0xA2, /* min, word, RW */ - 0xA0, /* max, word, RW */ -}; - -#define DS620_REG_CONF 0xAC /* word, RW */ -#define DS620_COM_START 0x51 /* no data */ -#define DS620_COM_STOP 0x22 /* no data */ - -/* Each client has this additional data */ -struct ds620_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - s16 temp[3]; /* Register values, word */ -}; - -static void ds620_init_client(struct i2c_client *client) -{ - struct ds620_platform_data *ds620_info = client->dev.platform_data; - u16 conf, new_conf; - - new_conf = conf = - i2c_smbus_read_word_swapped(client, DS620_REG_CONF); - - /* switch to continuous conversion mode */ - new_conf &= ~DS620_REG_CONFIG_1SHOT; - /* already high at power-on, but don't trust the BIOS! */ - new_conf |= DS620_REG_CONFIG_PO2; - /* thermostat mode according to platform data */ - if (ds620_info && ds620_info->pomode == 1) - new_conf &= ~DS620_REG_CONFIG_PO1; /* PO_LOW */ - else if (ds620_info && ds620_info->pomode == 2) - new_conf |= DS620_REG_CONFIG_PO1; /* PO_HIGH */ - else - new_conf &= ~DS620_REG_CONFIG_PO2; /* always low */ - /* with highest precision */ - new_conf |= DS620_REG_CONFIG_R1 | DS620_REG_CONFIG_R0; - - if (conf != new_conf) - i2c_smbus_write_word_swapped(client, DS620_REG_CONF, new_conf); - - /* start conversion */ - i2c_smbus_write_byte(client, DS620_COM_START); -} - -static struct ds620_data *ds620_update_client(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ds620_data *data = i2c_get_clientdata(client); - struct ds620_data *ret = data; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - int res; - - dev_dbg(&client->dev, "Starting ds620 update\n"); - - for (i = 0; i < ARRAY_SIZE(data->temp); i++) { - res = i2c_smbus_read_word_swapped(client, - DS620_REG_TEMP[i]); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - - data->temp[i] = res; - } - - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - - return ret; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ds620_data *data = ds620_update_client(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", ((data->temp[attr->index] / 8) * 625) / 10); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - int res; - long val; - - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct ds620_data *data = i2c_get_clientdata(client); - - res = kstrtol(buf, 10, &val); - - if (res) - return res; - - val = (val * 10 / 625) * 8; - - mutex_lock(&data->update_lock); - data->temp[attr->index] = val; - i2c_smbus_write_word_swapped(client, DS620_REG_TEMP[attr->index], - data->temp[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ds620_data *data = ds620_update_client(dev); - struct i2c_client *client = to_i2c_client(dev); - u16 conf, new_conf; - int res; - - if (IS_ERR(data)) - return PTR_ERR(data); - - /* reset alarms if necessary */ - res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF); - if (res < 0) - return res; - - new_conf = conf = res; - new_conf &= ~attr->index; - if (conf != new_conf) { - res = i2c_smbus_write_word_swapped(client, DS620_REG_CONF, - new_conf); - if (res < 0) - return res; - } - - return sprintf(buf, "%d\n", !!(conf & attr->index)); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, - DS620_REG_CONFIG_TLF); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, - DS620_REG_CONFIG_THF); - -static struct attribute *ds620_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group ds620_group = { - .attrs = ds620_attributes, -}; - -static int ds620_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct ds620_data *data; - int err; - - data = kzalloc(sizeof(struct ds620_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the DS620 chip */ - ds620_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &ds620_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - dev_info(&client->dev, "temperature sensor found\n"); - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &ds620_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int ds620_remove(struct i2c_client *client) -{ - struct ds620_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ds620_group); - - kfree(data); - - return 0; -} - -static const struct i2c_device_id ds620_id[] = { - {"ds620", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ds620_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ds620_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "ds620", - }, - .probe = ds620_probe, - .remove = ds620_remove, - .id_table = ds620_id, -}; - -module_i2c_driver(ds620_driver); - -MODULE_AUTHOR("Roland Stigge "); -MODULE_DESCRIPTION("DS620 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/emc1403.c b/ANDROID_3.4.5/drivers/hwmon/emc1403.c deleted file mode 100644 index 149dcb0e..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/emc1403.c +++ /dev/null @@ -1,377 +0,0 @@ -/* - * emc1403.c - SMSC Thermal Driver - * - * Copyright (C) 2008 Intel Corp - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * 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., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * TODO - * - cache alarm and critical limit registers - * - add emc1404 support - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define THERMAL_PID_REG 0xfd -#define THERMAL_SMSC_ID_REG 0xfe -#define THERMAL_REVISION_REG 0xff - -struct thermal_data { - struct device *hwmon_dev; - struct mutex mutex; - /* - * Cache the hyst value so we don't keep re-reading it. In theory - * we could cache it forever as nobody else should be writing it. - */ - u8 cached_hyst; - unsigned long hyst_valid; -}; - -static ssize_t show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - int retval = i2c_smbus_read_byte_data(client, sda->index); - - if (retval < 0) - return retval; - return sprintf(buf, "%d000\n", retval); -} - -static ssize_t show_bit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); - int retval = i2c_smbus_read_byte_data(client, sda->nr); - - if (retval < 0) - return retval; - retval &= sda->index; - return sprintf(buf, "%d\n", retval ? 1 : 0); -} - -static ssize_t store_temp(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - unsigned long val; - int retval; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - retval = i2c_smbus_write_byte_data(client, sda->index, - DIV_ROUND_CLOSEST(val, 1000)); - if (retval < 0) - return retval; - return count; -} - -static ssize_t store_bit(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct thermal_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sda = to_sensor_dev_attr_2(attr); - unsigned long val; - int retval; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->mutex); - retval = i2c_smbus_read_byte_data(client, sda->nr); - if (retval < 0) - goto fail; - - retval &= ~sda->index; - if (val) - retval |= sda->index; - - retval = i2c_smbus_write_byte_data(client, sda->index, retval); - if (retval == 0) - retval = count; -fail: - mutex_unlock(&data->mutex); - return retval; -} - -static ssize_t show_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct thermal_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - int retval; - int hyst; - - retval = i2c_smbus_read_byte_data(client, sda->index); - if (retval < 0) - return retval; - - if (time_after(jiffies, data->hyst_valid)) { - hyst = i2c_smbus_read_byte_data(client, 0x21); - if (hyst < 0) - return retval; - data->cached_hyst = hyst; - data->hyst_valid = jiffies + HZ; - } - return sprintf(buf, "%d000\n", retval - data->cached_hyst); -} - -static ssize_t store_hyst(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct thermal_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - int retval; - int hyst; - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->mutex); - retval = i2c_smbus_read_byte_data(client, sda->index); - if (retval < 0) - goto fail; - - hyst = val - retval * 1000; - hyst = DIV_ROUND_CLOSEST(hyst, 1000); - if (hyst < 0 || hyst > 255) { - retval = -ERANGE; - goto fail; - } - - retval = i2c_smbus_write_byte_data(client, 0x21, hyst); - if (retval == 0) { - retval = count; - data->cached_hyst = hyst; - data->hyst_valid = jiffies + HZ; - } -fail: - mutex_unlock(&data->mutex); - return retval; -} - -/* - * Sensors. We pass the actual i2c register to the methods. - */ - -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x06); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x05); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x20); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0x00); -static SENSOR_DEVICE_ATTR_2(temp1_min_alarm, S_IRUGO, - show_bit, NULL, 0x36, 0x01); -static SENSOR_DEVICE_ATTR_2(temp1_max_alarm, S_IRUGO, - show_bit, NULL, 0x35, 0x01); -static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, - show_bit, NULL, 0x37, 0x01); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO | S_IWUSR, - show_hyst, store_hyst, 0x20); - -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x08); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x07); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x19); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0x01); -static SENSOR_DEVICE_ATTR_2(temp2_min_alarm, S_IRUGO, - show_bit, NULL, 0x36, 0x02); -static SENSOR_DEVICE_ATTR_2(temp2_max_alarm, S_IRUGO, - show_bit, NULL, 0x35, 0x02); -static SENSOR_DEVICE_ATTR_2(temp2_crit_alarm, S_IRUGO, - show_bit, NULL, 0x37, 0x02); -static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO | S_IWUSR, - show_hyst, store_hyst, 0x19); - -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x16); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x15); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO | S_IWUSR, - show_temp, store_temp, 0x1A); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 0x23); -static SENSOR_DEVICE_ATTR_2(temp3_min_alarm, S_IRUGO, - show_bit, NULL, 0x36, 0x04); -static SENSOR_DEVICE_ATTR_2(temp3_max_alarm, S_IRUGO, - show_bit, NULL, 0x35, 0x04); -static SENSOR_DEVICE_ATTR_2(temp3_crit_alarm, S_IRUGO, - show_bit, NULL, 0x37, 0x04); -static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO | S_IWUSR, - show_hyst, store_hyst, 0x1A); - -static SENSOR_DEVICE_ATTR_2(power_state, S_IRUGO | S_IWUSR, - show_bit, store_bit, 0x03, 0x40); - -static struct attribute *mid_att_thermal[] = { - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, - &sensor_dev_attr_power_state.dev_attr.attr, - NULL -}; - -static const struct attribute_group m_thermal_gr = { - .attrs = mid_att_thermal -}; - -static int emc1403_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - int id; - /* Check if thermal chip is SMSC and EMC1403 or EMC1423 */ - - id = i2c_smbus_read_byte_data(client, THERMAL_SMSC_ID_REG); - if (id != 0x5d) - return -ENODEV; - - id = i2c_smbus_read_byte_data(client, THERMAL_PID_REG); - switch (id) { - case 0x21: - strlcpy(info->type, "emc1403", I2C_NAME_SIZE); - break; - case 0x23: - strlcpy(info->type, "emc1423", I2C_NAME_SIZE); - break; - /* - * Note: 0x25 is the 1404 which is very similar and this - * driver could be extended - */ - default: - return -ENODEV; - } - - id = i2c_smbus_read_byte_data(client, THERMAL_REVISION_REG); - if (id != 0x01) - return -ENODEV; - - return 0; -} - -static int emc1403_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int res; - struct thermal_data *data; - - data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL); - if (data == NULL) { - dev_warn(&client->dev, "out of memory"); - return -ENOMEM; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->mutex); - data->hyst_valid = jiffies - 1; /* Expired */ - - res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr); - if (res) { - dev_warn(&client->dev, "create group failed\n"); - goto thermal_error1; - } - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - res = PTR_ERR(data->hwmon_dev); - dev_warn(&client->dev, "register hwmon dev failed\n"); - goto thermal_error2; - } - dev_info(&client->dev, "EMC1403 Thermal chip found\n"); - return res; - -thermal_error2: - sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); -thermal_error1: - kfree(data); - return res; -} - -static int emc1403_remove(struct i2c_client *client) -{ - struct thermal_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); - kfree(data); - return 0; -} - -static const unsigned short emc1403_address_list[] = { - 0x18, 0x29, 0x4c, 0x4d, I2C_CLIENT_END -}; - -static const struct i2c_device_id emc1403_idtable[] = { - { "emc1403", 0 }, - { "emc1423", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, emc1403_idtable); - -static struct i2c_driver sensor_emc1403 = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "emc1403", - }, - .detect = emc1403_detect, - .probe = emc1403_probe, - .remove = emc1403_remove, - .id_table = emc1403_idtable, - .address_list = emc1403_address_list, -}; - -module_i2c_driver(sensor_emc1403); - -MODULE_AUTHOR("Kalhan Trisal -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses scanned */ -static const unsigned short normal_i2c[] = { 0x2E, I2C_CLIENT_END }; - -static const u8 REG_TEMP[4] = { 0x00, 0x02, 0x04, 0x06 }; -static const u8 REG_TEMP_MIN[4] = { 0x3c, 0x38, 0x39, 0x3a }; -static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 }; - -#define REG_CONF1 0x20 -#define REG_TEMP_MAX_ALARM 0x24 -#define REG_TEMP_MIN_ALARM 0x25 -#define REG_FAN_CONF1 0x42 -#define REG_FAN_TARGET_LO 0x4c -#define REG_FAN_TARGET_HI 0x4d -#define REG_FAN_TACH_HI 0x4e -#define REG_FAN_TACH_LO 0x4f -#define REG_PRODUCT_ID 0xfd -#define REG_MFG_ID 0xfe - -/* equation 4 from datasheet: rpm = (3932160 * multipler) / count */ -#define FAN_RPM_FACTOR 3932160 - -/* - * 2103-2 and 2103-4's 3rd temperature sensor can be connected to two diodes - * in anti-parallel mode, and in this configuration both can be read - * independently (so we have 4 temperature inputs). The device can't - * detect if it's connected in this mode, so we have to manually enable - * it. Default is to leave the device in the state it's already in (-1). - * This parameter allows APD mode to be optionally forced on or off - */ -static int apd = -1; -module_param(apd, bint, 0); -MODULE_PARM_DESC(init, "Set to zero to disable anti-parallel diode mode"); - -struct temperature { - s8 degrees; - u8 fraction; /* 0-7 multiples of 0.125 */ -}; - -struct emc2103_data { - struct device *hwmon_dev; - struct mutex update_lock; - bool valid; /* registers are valid */ - bool fan_rpm_control; - int temp_count; /* num of temp sensors */ - unsigned long last_updated; /* in jiffies */ - struct temperature temp[4]; /* internal + 3 external */ - s8 temp_min[4]; /* no fractional part */ - s8 temp_max[4]; /* no fractional part */ - u8 temp_min_alarm; - u8 temp_max_alarm; - u8 fan_multiplier; - u16 fan_tach; - u16 fan_target; -}; - -static int read_u8_from_i2c(struct i2c_client *client, u8 i2c_reg, u8 *output) -{ - int status = i2c_smbus_read_byte_data(client, i2c_reg); - if (status < 0) { - dev_warn(&client->dev, "reg 0x%02x, err %d\n", - i2c_reg, status); - } else { - *output = status; - } - return status; -} - -static void read_temp_from_i2c(struct i2c_client *client, u8 i2c_reg, - struct temperature *temp) -{ - u8 degrees, fractional; - - if (read_u8_from_i2c(client, i2c_reg, °rees) < 0) - return; - - if (read_u8_from_i2c(client, i2c_reg + 1, &fractional) < 0) - return; - - temp->degrees = degrees; - temp->fraction = (fractional & 0xe0) >> 5; -} - -static void read_fan_from_i2c(struct i2c_client *client, u16 *output, - u8 hi_addr, u8 lo_addr) -{ - u8 high_byte, lo_byte; - - if (read_u8_from_i2c(client, hi_addr, &high_byte) < 0) - return; - - if (read_u8_from_i2c(client, lo_addr, &lo_byte) < 0) - return; - - *output = ((u16)high_byte << 5) | (lo_byte >> 3); -} - -static void write_fan_target_to_i2c(struct i2c_client *client, u16 new_target) -{ - u8 high_byte = (new_target & 0x1fe0) >> 5; - u8 low_byte = (new_target & 0x001f) << 3; - i2c_smbus_write_byte_data(client, REG_FAN_TARGET_LO, low_byte); - i2c_smbus_write_byte_data(client, REG_FAN_TARGET_HI, high_byte); -} - -static void read_fan_config_from_i2c(struct i2c_client *client) - -{ - struct emc2103_data *data = i2c_get_clientdata(client); - u8 conf1; - - if (read_u8_from_i2c(client, REG_FAN_CONF1, &conf1) < 0) - return; - - data->fan_multiplier = 1 << ((conf1 & 0x60) >> 5); - data->fan_rpm_control = (conf1 & 0x80) != 0; -} - -static struct emc2103_data *emc2103_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - - for (i = 0; i < data->temp_count; i++) { - read_temp_from_i2c(client, REG_TEMP[i], &data->temp[i]); - read_u8_from_i2c(client, REG_TEMP_MIN[i], - &data->temp_min[i]); - read_u8_from_i2c(client, REG_TEMP_MAX[i], - &data->temp_max[i]); - } - - read_u8_from_i2c(client, REG_TEMP_MIN_ALARM, - &data->temp_min_alarm); - read_u8_from_i2c(client, REG_TEMP_MAX_ALARM, - &data->temp_max_alarm); - - read_fan_from_i2c(client, &data->fan_tach, - REG_FAN_TACH_HI, REG_FAN_TACH_LO); - read_fan_from_i2c(client, &data->fan_target, - REG_FAN_TARGET_HI, REG_FAN_TARGET_LO); - read_fan_config_from_i2c(client); - - data->last_updated = jiffies; - data->valid = true; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static ssize_t -show_temp(struct device *dev, struct device_attribute *da, char *buf) -{ - int nr = to_sensor_dev_attr(da)->index; - struct emc2103_data *data = emc2103_update_device(dev); - int millidegrees = data->temp[nr].degrees * 1000 - + data->temp[nr].fraction * 125; - return sprintf(buf, "%d\n", millidegrees); -} - -static ssize_t -show_temp_min(struct device *dev, struct device_attribute *da, char *buf) -{ - int nr = to_sensor_dev_attr(da)->index; - struct emc2103_data *data = emc2103_update_device(dev); - int millidegrees = data->temp_min[nr] * 1000; - return sprintf(buf, "%d\n", millidegrees); -} - -static ssize_t -show_temp_max(struct device *dev, struct device_attribute *da, char *buf) -{ - int nr = to_sensor_dev_attr(da)->index; - struct emc2103_data *data = emc2103_update_device(dev); - int millidegrees = data->temp_max[nr] * 1000; - return sprintf(buf, "%d\n", millidegrees); -} - -static ssize_t -show_temp_fault(struct device *dev, struct device_attribute *da, char *buf) -{ - int nr = to_sensor_dev_attr(da)->index; - struct emc2103_data *data = emc2103_update_device(dev); - bool fault = (data->temp[nr].degrees == -128); - return sprintf(buf, "%d\n", fault ? 1 : 0); -} - -static ssize_t -show_temp_min_alarm(struct device *dev, struct device_attribute *da, char *buf) -{ - int nr = to_sensor_dev_attr(da)->index; - struct emc2103_data *data = emc2103_update_device(dev); - bool alarm = data->temp_min_alarm & (1 << nr); - return sprintf(buf, "%d\n", alarm ? 1 : 0); -} - -static ssize_t -show_temp_max_alarm(struct device *dev, struct device_attribute *da, char *buf) -{ - int nr = to_sensor_dev_attr(da)->index; - struct emc2103_data *data = emc2103_update_device(dev); - bool alarm = data->temp_max_alarm & (1 << nr); - return sprintf(buf, "%d\n", alarm ? 1 : 0); -} - -static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(da)->index; - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); - long val; - - int result = kstrtol(buf, 10, &val); - if (result < 0) - return -EINVAL; - - val = DIV_ROUND_CLOSEST(val, 1000); - if ((val < -63) || (val > 127)) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->temp_min[nr] = val; - i2c_smbus_write_byte_data(client, REG_TEMP_MIN[nr], val); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(da)->index; - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); - long val; - - int result = kstrtol(buf, 10, &val); - if (result < 0) - return -EINVAL; - - val = DIV_ROUND_CLOSEST(val, 1000); - if ((val < -63) || (val > 127)) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = val; - i2c_smbus_write_byte_data(client, REG_TEMP_MAX[nr], val); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_fan(struct device *dev, struct device_attribute *da, char *buf) -{ - struct emc2103_data *data = emc2103_update_device(dev); - int rpm = 0; - if (data->fan_tach != 0) - rpm = (FAN_RPM_FACTOR * data->fan_multiplier) / data->fan_tach; - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t -show_fan_div(struct device *dev, struct device_attribute *da, char *buf) -{ - struct emc2103_data *data = emc2103_update_device(dev); - int fan_div = 8 / data->fan_multiplier; - return sprintf(buf, "%d\n", fan_div); -} - -/* - * Note: we also update the fan target here, because its value is - * determined in part by the fan clock divider. This follows the principle - * of least surprise; the user doesn't expect the fan target to change just - * because the divider changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct emc2103_data *data = emc2103_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); - int new_range_bits, old_div = 8 / data->fan_multiplier; - long new_div; - - int status = kstrtol(buf, 10, &new_div); - if (status < 0) - return -EINVAL; - - if (new_div == old_div) /* No change */ - return count; - - switch (new_div) { - case 1: - new_range_bits = 3; - break; - case 2: - new_range_bits = 2; - break; - case 4: - new_range_bits = 1; - break; - case 8: - new_range_bits = 0; - break; - default: - return -EINVAL; - } - - mutex_lock(&data->update_lock); - - status = i2c_smbus_read_byte_data(client, REG_FAN_CONF1); - if (status < 0) { - dev_dbg(&client->dev, "reg 0x%02x, err %d\n", - REG_FAN_CONF1, status); - mutex_unlock(&data->update_lock); - return -EIO; - } - status &= 0x9F; - status |= (new_range_bits << 5); - i2c_smbus_write_byte_data(client, REG_FAN_CONF1, status); - - data->fan_multiplier = 8 / new_div; - - /* update fan target if high byte is not disabled */ - if ((data->fan_target & 0x1fe0) != 0x1fe0) { - u16 new_target = (data->fan_target * old_div) / new_div; - data->fan_target = min(new_target, (u16)0x1fff); - write_fan_target_to_i2c(client, data->fan_target); - } - - /* invalidate data to force re-read from hardware */ - data->valid = false; - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_fan_target(struct device *dev, struct device_attribute *da, char *buf) -{ - struct emc2103_data *data = emc2103_update_device(dev); - int rpm = 0; - - /* high byte of 0xff indicates disabled so return 0 */ - if ((data->fan_target != 0) && ((data->fan_target & 0x1fe0) != 0x1fe0)) - rpm = (FAN_RPM_FACTOR * data->fan_multiplier) - / data->fan_target; - - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct emc2103_data *data = emc2103_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); - long rpm_target; - - int result = kstrtol(buf, 10, &rpm_target); - if (result < 0) - return -EINVAL; - - /* Datasheet states 16384 as maximum RPM target (table 3.2) */ - if ((rpm_target < 0) || (rpm_target > 16384)) - return -EINVAL; - - mutex_lock(&data->update_lock); - - if (rpm_target == 0) - data->fan_target = 0x1fff; - else - data->fan_target = SENSORS_LIMIT( - (FAN_RPM_FACTOR * data->fan_multiplier) / rpm_target, - 0, 0x1fff); - - write_fan_target_to_i2c(client, data->fan_target); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_fan_fault(struct device *dev, struct device_attribute *da, char *buf) -{ - struct emc2103_data *data = emc2103_update_device(dev); - bool fault = ((data->fan_tach & 0x1fe0) == 0x1fe0); - return sprintf(buf, "%d\n", fault ? 1 : 0); -} - -static ssize_t -show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) -{ - struct emc2103_data *data = emc2103_update_device(dev); - return sprintf(buf, "%d\n", data->fan_rpm_control ? 3 : 0); -} - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); - long new_value; - u8 conf_reg; - - int result = kstrtol(buf, 10, &new_value); - if (result < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - switch (new_value) { - case 0: - data->fan_rpm_control = false; - break; - case 3: - data->fan_rpm_control = true; - break; - default: - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - read_u8_from_i2c(client, REG_FAN_CONF1, &conf_reg); - - if (data->fan_rpm_control) - conf_reg |= 0x80; - else - conf_reg &= ~0x80; - - i2c_smbus_write_byte_data(client, REG_FAN_CONF1, conf_reg); - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, show_temp_min, - set_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, - NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, - NULL, 0); - -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO | S_IWUSR, show_temp_min, - set_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, - NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, - NULL, 1); - -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO | S_IWUSR, show_temp_min, - set_temp_min, 2); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, - set_temp_max, 2); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, - NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, - NULL, 2); - -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO | S_IWUSR, show_temp_min, - set_temp_min, 3); -static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max, - set_temp_max, 3); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_temp_min_alarm, - NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_temp_max_alarm, - NULL, 3); - -static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL); -static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, show_fan_div, set_fan_div); -static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_fan_target, - set_fan_target); -static DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL); - -static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, show_pwm_enable, - set_pwm_enable); - -/* sensors present on all models */ -static struct attribute *emc2103_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan1_div.attr, - &dev_attr_fan1_target.attr, - &dev_attr_fan1_fault.attr, - &dev_attr_pwm1_enable.attr, - NULL -}; - -/* extra temperature sensors only present on 2103-2 and 2103-4 */ -static struct attribute *emc2103_attributes_temp3[] = { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - NULL -}; - -/* extra temperature sensors only present on 2103-2 and 2103-4 in APD mode */ -static struct attribute *emc2103_attributes_temp4[] = { - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_fault.dev_attr.attr, - &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group emc2103_group = { - .attrs = emc2103_attributes, -}; - -static const struct attribute_group emc2103_temp3_group = { - .attrs = emc2103_attributes_temp3, -}; - -static const struct attribute_group emc2103_temp4_group = { - .attrs = emc2103_attributes_temp4, -}; - -static int -emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct emc2103_data *data; - int status; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */ - status = i2c_smbus_read_byte_data(client, REG_PRODUCT_ID); - if (status == 0x24) { - /* 2103-1 only has 1 external diode */ - data->temp_count = 2; - } else { - /* 2103-2 and 2103-4 have 3 or 4 external diodes */ - status = i2c_smbus_read_byte_data(client, REG_CONF1); - if (status < 0) { - dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, - status); - goto exit_free; - } - - /* detect current state of hardware */ - data->temp_count = (status & 0x01) ? 4 : 3; - - /* force APD state if module parameter is set */ - if (apd == 0) { - /* force APD mode off */ - data->temp_count = 3; - status &= ~(0x01); - i2c_smbus_write_byte_data(client, REG_CONF1, status); - } else if (apd == 1) { - /* force APD mode on */ - data->temp_count = 4; - status |= 0x01; - i2c_smbus_write_byte_data(client, REG_CONF1, status); - } - } - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &emc2103_group); - if (status) - goto exit_free; - - if (data->temp_count >= 3) { - status = sysfs_create_group(&client->dev.kobj, - &emc2103_temp3_group); - if (status) - goto exit_remove; - } - - if (data->temp_count == 4) { - status = sysfs_create_group(&client->dev.kobj, - &emc2103_temp4_group); - if (status) - goto exit_remove_temp3; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove_temp4; - } - - dev_info(&client->dev, "%s: sensor '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove_temp4: - if (data->temp_count == 4) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); -exit_remove_temp3: - if (data->temp_count >= 3) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); -exit_remove: - sysfs_remove_group(&client->dev.kobj, &emc2103_group); -exit_free: - kfree(data); - return status; -} - -static int emc2103_remove(struct i2c_client *client) -{ - struct emc2103_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - - if (data->temp_count == 4) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); - - if (data->temp_count >= 3) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); - - sysfs_remove_group(&client->dev.kobj, &emc2103_group); - - kfree(data); - return 0; -} - -static const struct i2c_device_id emc2103_ids[] = { - { "emc2103", 0, }, - { /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, emc2103_ids); - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int -emc2103_detect(struct i2c_client *new_client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - int manufacturer, product; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - manufacturer = i2c_smbus_read_byte_data(new_client, REG_MFG_ID); - if (manufacturer != 0x5D) - return -ENODEV; - - product = i2c_smbus_read_byte_data(new_client, REG_PRODUCT_ID); - if ((product != 0x24) && (product != 0x26)) - return -ENODEV; - - strlcpy(info->type, "emc2103", I2C_NAME_SIZE); - - return 0; -} - -static struct i2c_driver emc2103_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "emc2103", - }, - .probe = emc2103_probe, - .remove = emc2103_remove, - .id_table = emc2103_ids, - .detect = emc2103_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(emc2103_driver); - -MODULE_AUTHOR("Steve Glendinning "); -MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/emc6w201.c b/ANDROID_3.4.5/drivers/hwmon/emc6w201.c deleted file mode 100644 index 840f5112..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/emc6w201.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * emc6w201.c - Hardware monitoring driver for the SMSC EMC6W201 - * Copyright (C) 2011 Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - */ - -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -/* - * The EMC6W201 registers - */ - -#define EMC6W201_REG_IN(nr) (0x20 + (nr)) -#define EMC6W201_REG_TEMP(nr) (0x26 + (nr)) -#define EMC6W201_REG_FAN(nr) (0x2C + (nr) * 2) -#define EMC6W201_REG_COMPANY 0x3E -#define EMC6W201_REG_VERSTEP 0x3F -#define EMC6W201_REG_CONFIG 0x40 -#define EMC6W201_REG_IN_LOW(nr) (0x4A + (nr) * 2) -#define EMC6W201_REG_IN_HIGH(nr) (0x4B + (nr) * 2) -#define EMC6W201_REG_TEMP_LOW(nr) (0x56 + (nr) * 2) -#define EMC6W201_REG_TEMP_HIGH(nr) (0x57 + (nr) * 2) -#define EMC6W201_REG_FAN_MIN(nr) (0x62 + (nr) * 2) - -enum { input, min, max } subfeature; - -/* - * Per-device data - */ - -struct emc6w201_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - u8 in[3][6]; - s8 temp[3][6]; - u16 fan[2][5]; -}; - -/* - * Combine LSB and MSB registers in a single value - * Locking: must be called with data->update_lock held - */ -static u16 emc6w201_read16(struct i2c_client *client, u8 reg) -{ - int lsb, msb; - - lsb = i2c_smbus_read_byte_data(client, reg); - msb = i2c_smbus_read_byte_data(client, reg + 1); - if (unlikely(lsb < 0 || msb < 0)) { - dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", - 16, "read", reg); - return 0xFFFF; /* Arbitrary value */ - } - - return (msb << 8) | lsb; -} - -/* - * Write 16-bit value to LSB and MSB registers - * Locking: must be called with data->update_lock held - */ -static int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val) -{ - int err; - - err = i2c_smbus_write_byte_data(client, reg, val & 0xff); - if (likely(!err)) - err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8); - if (unlikely(err < 0)) - dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", - 16, "write", reg); - - return err; -} - -/* Read 8-bit value from register */ -static u8 emc6w201_read8(struct i2c_client *client, u8 reg) -{ - int val; - - val = i2c_smbus_read_byte_data(client, reg); - if (unlikely(val < 0)) { - dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", - 8, "read", reg); - return 0x00; /* Arbitrary value */ - } - - return val; -} - -/* Write 8-bit value to register */ -static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val) -{ - int err; - - err = i2c_smbus_write_byte_data(client, reg, val); - if (unlikely(err < 0)) - dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n", - 8, "write", reg); - - return err; -} - -static struct emc6w201_data *emc6w201_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); - int nr; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - for (nr = 0; nr < 6; nr++) { - data->in[input][nr] = - emc6w201_read8(client, - EMC6W201_REG_IN(nr)); - data->in[min][nr] = - emc6w201_read8(client, - EMC6W201_REG_IN_LOW(nr)); - data->in[max][nr] = - emc6w201_read8(client, - EMC6W201_REG_IN_HIGH(nr)); - } - - for (nr = 0; nr < 6; nr++) { - data->temp[input][nr] = - emc6w201_read8(client, - EMC6W201_REG_TEMP(nr)); - data->temp[min][nr] = - emc6w201_read8(client, - EMC6W201_REG_TEMP_LOW(nr)); - data->temp[max][nr] = - emc6w201_read8(client, - EMC6W201_REG_TEMP_HIGH(nr)); - } - - for (nr = 0; nr < 5; nr++) { - data->fan[input][nr] = - emc6w201_read16(client, - EMC6W201_REG_FAN(nr)); - data->fan[min][nr] = - emc6w201_read16(client, - EMC6W201_REG_FAN_MIN(nr)); - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Sysfs callback functions - */ - -static const u16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 }; - -static ssize_t show_in(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct emc6w201_data *data = emc6w201_update_device(dev); - int sf = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - - return sprintf(buf, "%u\n", - (unsigned)data->in[sf][nr] * nominal_mv[nr] / 0xC0); -} - -static ssize_t set_in(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); - int sf = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - int err; - long val; - u8 reg; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - val = DIV_ROUND_CLOSEST(val * 0xC0, nominal_mv[nr]); - reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr) - : EMC6W201_REG_IN_HIGH(nr); - - mutex_lock(&data->update_lock); - data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255); - err = emc6w201_write8(client, reg, data->in[sf][nr]); - mutex_unlock(&data->update_lock); - - return err < 0 ? err : count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct emc6w201_data *data = emc6w201_update_device(dev); - int sf = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - - return sprintf(buf, "%d\n", (int)data->temp[sf][nr] * 1000); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); - int sf = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - int err; - long val; - u8 reg; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - val /= 1000; - reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr) - : EMC6W201_REG_TEMP_HIGH(nr); - - mutex_lock(&data->update_lock); - data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128); - err = emc6w201_write8(client, reg, data->temp[sf][nr]); - mutex_unlock(&data->update_lock); - - return err < 0 ? err : count; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct emc6w201_data *data = emc6w201_update_device(dev); - int sf = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - unsigned rpm; - - if (data->fan[sf][nr] == 0 || data->fan[sf][nr] == 0xFFFF) - rpm = 0; - else - rpm = 5400000U / data->fan[sf][nr]; - - return sprintf(buf, "%u\n", rpm); -} - -static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); - int sf = to_sensor_dev_attr_2(devattr)->index; - int nr = to_sensor_dev_attr_2(devattr)->nr; - int err; - unsigned long val; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - if (val == 0) { - val = 0xFFFF; - } else { - val = DIV_ROUND_CLOSEST(5400000U, val); - val = SENSORS_LIMIT(val, 0, 0xFFFE); - } - - mutex_lock(&data->update_lock); - data->fan[sf][nr] = val; - err = emc6w201_write16(client, EMC6W201_REG_FAN_MIN(nr), - data->fan[sf][nr]); - mutex_unlock(&data->update_lock); - - return err < 0 ? err : count; -} - -static SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, input); -static SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in, - 0, min); -static SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in, - 0, max); -static SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, input); -static SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in, - 1, min); -static SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in, - 1, max); -static SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, input); -static SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in, - 2, min); -static SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in, - 2, max); -static SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, input); -static SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in, - 3, min); -static SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in, - 3, max); -static SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, input); -static SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in, - 4, min); -static SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in, - 4, max); -static SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, input); -static SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in, - 5, min); -static SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in, - 5, max); - -static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, input); -static SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - 0, min); -static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - 0, max); -static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, input); -static SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - 1, min); -static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - 1, max); -static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, input); -static SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - 2, min); -static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - 2, max); -static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, input); -static SENSOR_DEVICE_ATTR_2(temp4_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - 3, min); -static SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - 3, max); -static SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, input); -static SENSOR_DEVICE_ATTR_2(temp5_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - 4, min); -static SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - 4, max); -static SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, input); -static SENSOR_DEVICE_ATTR_2(temp6_min, S_IRUGO | S_IWUSR, show_temp, set_temp, - 5, min); -static SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp, - 5, max); - -static SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, input); -static SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan, - 0, min); -static SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, input); -static SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan, - 1, min); -static SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, input); -static SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan, - 2, min); -static SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, input); -static SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan, - 3, min); -static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, input); -static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan, - 4, min); - -static struct attribute *emc6w201_attributes[] = { - &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_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &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_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &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_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp5_min.dev_attr.attr, - &sensor_dev_attr_temp5_max.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp6_min.dev_attr.attr, - &sensor_dev_attr_temp6_max.dev_attr.attr, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan5_input.dev_attr.attr, - &sensor_dev_attr_fan5_min.dev_attr.attr, - NULL -}; - -static const struct attribute_group emc6w201_group = { - .attrs = emc6w201_attributes, -}; - -/* - * Driver interface - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int emc6w201_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int company, verstep, config; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Identification */ - company = i2c_smbus_read_byte_data(client, EMC6W201_REG_COMPANY); - if (company != 0x5C) - return -ENODEV; - verstep = i2c_smbus_read_byte_data(client, EMC6W201_REG_VERSTEP); - if (verstep < 0 || (verstep & 0xF0) != 0xB0) - return -ENODEV; - if ((verstep & 0x0F) > 2) { - dev_dbg(&client->dev, "Unknwown EMC6W201 stepping %d\n", - verstep & 0x0F); - return -ENODEV; - } - - /* Check configuration */ - config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG); - if (config < 0 || (config & 0xF4) != 0x04) - return -ENODEV; - if (!(config & 0x01)) { - dev_err(&client->dev, "Monitoring not enabled\n"); - return -ENODEV; - } - - strlcpy(info->type, "emc6w201", I2C_NAME_SIZE); - - return 0; -} - -static int emc6w201_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct emc6w201_data *data; - int err; - - data = kzalloc(sizeof(struct emc6w201_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Create sysfs attribute */ - err = sysfs_create_group(&client->dev.kobj, &emc6w201_group); - if (err) - goto exit_free; - - /* Expose as a hwmon device */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - - exit_remove: - sysfs_remove_group(&client->dev.kobj, &emc6w201_group); - exit_free: - kfree(data); - exit: - return err; -} - -static int emc6w201_remove(struct i2c_client *client) -{ - struct emc6w201_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &emc6w201_group); - kfree(data); - - return 0; -} - -static const struct i2c_device_id emc6w201_id[] = { - { "emc6w201", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, emc6w201_id); - -static struct i2c_driver emc6w201_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "emc6w201", - }, - .probe = emc6w201_probe, - .remove = emc6w201_remove, - .id_table = emc6w201_id, - .detect = emc6w201_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(emc6w201_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("SMSC EMC6W201 hardware monitoring driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/exynos4_tmu.c b/ANDROID_3.4.5/drivers/hwmon/exynos4_tmu.c deleted file mode 100644 index f2359a00..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/exynos4_tmu.c +++ /dev/null @@ -1,514 +0,0 @@ -/* - * exynos4_tmu.c - Samsung EXYNOS4 TMU (Thermal Management Unit) - * - * Copyright (C) 2011 Samsung Electronics - * Donggeun Kim - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -#define EXYNOS4_TMU_REG_TRIMINFO 0x0 -#define EXYNOS4_TMU_REG_CONTROL 0x20 -#define EXYNOS4_TMU_REG_STATUS 0x28 -#define EXYNOS4_TMU_REG_CURRENT_TEMP 0x40 -#define EXYNOS4_TMU_REG_THRESHOLD_TEMP 0x44 -#define EXYNOS4_TMU_REG_TRIG_LEVEL0 0x50 -#define EXYNOS4_TMU_REG_TRIG_LEVEL1 0x54 -#define EXYNOS4_TMU_REG_TRIG_LEVEL2 0x58 -#define EXYNOS4_TMU_REG_TRIG_LEVEL3 0x5C -#define EXYNOS4_TMU_REG_PAST_TEMP0 0x60 -#define EXYNOS4_TMU_REG_PAST_TEMP1 0x64 -#define EXYNOS4_TMU_REG_PAST_TEMP2 0x68 -#define EXYNOS4_TMU_REG_PAST_TEMP3 0x6C -#define EXYNOS4_TMU_REG_INTEN 0x70 -#define EXYNOS4_TMU_REG_INTSTAT 0x74 -#define EXYNOS4_TMU_REG_INTCLEAR 0x78 - -#define EXYNOS4_TMU_GAIN_SHIFT 8 -#define EXYNOS4_TMU_REF_VOLTAGE_SHIFT 24 - -#define EXYNOS4_TMU_TRIM_TEMP_MASK 0xff -#define EXYNOS4_TMU_CORE_ON 3 -#define EXYNOS4_TMU_CORE_OFF 2 -#define EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET 50 -#define EXYNOS4_TMU_TRIG_LEVEL0_MASK 0x1 -#define EXYNOS4_TMU_TRIG_LEVEL1_MASK 0x10 -#define EXYNOS4_TMU_TRIG_LEVEL2_MASK 0x100 -#define EXYNOS4_TMU_TRIG_LEVEL3_MASK 0x1000 -#define EXYNOS4_TMU_INTCLEAR_VAL 0x1111 - -struct exynos4_tmu_data { - struct exynos4_tmu_platform_data *pdata; - struct device *hwmon_dev; - struct resource *mem; - void __iomem *base; - int irq; - struct work_struct irq_work; - struct mutex lock; - struct clk *clk; - u8 temp_error1, temp_error2; -}; - -/* - * TMU treats temperature as a mapped temperature code. - * The temperature is converted differently depending on the calibration type. - */ -static int temp_to_code(struct exynos4_tmu_data *data, u8 temp) -{ - struct exynos4_tmu_platform_data *pdata = data->pdata; - int temp_code; - - /* temp should range between 25 and 125 */ - if (temp < 25 || temp > 125) { - temp_code = -EINVAL; - goto out; - } - - switch (pdata->cal_type) { - case TYPE_TWO_POINT_TRIMMING: - temp_code = (temp - 25) * - (data->temp_error2 - data->temp_error1) / - (85 - 25) + data->temp_error1; - break; - case TYPE_ONE_POINT_TRIMMING: - temp_code = temp + data->temp_error1 - 25; - break; - default: - temp_code = temp + EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET; - break; - } -out: - return temp_code; -} - -/* - * Calculate a temperature value from a temperature code. - * The unit of the temperature is degree Celsius. - */ -static int code_to_temp(struct exynos4_tmu_data *data, u8 temp_code) -{ - struct exynos4_tmu_platform_data *pdata = data->pdata; - int temp; - - /* temp_code should range between 75 and 175 */ - if (temp_code < 75 || temp_code > 175) { - temp = -ENODATA; - goto out; - } - - switch (pdata->cal_type) { - case TYPE_TWO_POINT_TRIMMING: - temp = (temp_code - data->temp_error1) * (85 - 25) / - (data->temp_error2 - data->temp_error1) + 25; - break; - case TYPE_ONE_POINT_TRIMMING: - temp = temp_code - data->temp_error1 + 25; - break; - default: - temp = temp_code - EXYNOS4_TMU_DEF_CODE_TO_TEMP_OFFSET; - break; - } -out: - return temp; -} - -static int exynos4_tmu_initialize(struct platform_device *pdev) -{ - struct exynos4_tmu_data *data = platform_get_drvdata(pdev); - struct exynos4_tmu_platform_data *pdata = data->pdata; - unsigned int status, trim_info; - int ret = 0, threshold_code; - - mutex_lock(&data->lock); - clk_enable(data->clk); - - status = readb(data->base + EXYNOS4_TMU_REG_STATUS); - if (!status) { - ret = -EBUSY; - goto out; - } - - /* Save trimming info in order to perform calibration */ - trim_info = readl(data->base + EXYNOS4_TMU_REG_TRIMINFO); - data->temp_error1 = trim_info & EXYNOS4_TMU_TRIM_TEMP_MASK; - data->temp_error2 = ((trim_info >> 8) & EXYNOS4_TMU_TRIM_TEMP_MASK); - - /* Write temperature code for threshold */ - threshold_code = temp_to_code(data, pdata->threshold); - if (threshold_code < 0) { - ret = threshold_code; - goto out; - } - writeb(threshold_code, - data->base + EXYNOS4_TMU_REG_THRESHOLD_TEMP); - - writeb(pdata->trigger_levels[0], - data->base + EXYNOS4_TMU_REG_TRIG_LEVEL0); - writeb(pdata->trigger_levels[1], - data->base + EXYNOS4_TMU_REG_TRIG_LEVEL1); - writeb(pdata->trigger_levels[2], - data->base + EXYNOS4_TMU_REG_TRIG_LEVEL2); - writeb(pdata->trigger_levels[3], - data->base + EXYNOS4_TMU_REG_TRIG_LEVEL3); - - writel(EXYNOS4_TMU_INTCLEAR_VAL, - data->base + EXYNOS4_TMU_REG_INTCLEAR); -out: - clk_disable(data->clk); - mutex_unlock(&data->lock); - - return ret; -} - -static void exynos4_tmu_control(struct platform_device *pdev, bool on) -{ - struct exynos4_tmu_data *data = platform_get_drvdata(pdev); - struct exynos4_tmu_platform_data *pdata = data->pdata; - unsigned int con, interrupt_en; - - mutex_lock(&data->lock); - clk_enable(data->clk); - - con = pdata->reference_voltage << EXYNOS4_TMU_REF_VOLTAGE_SHIFT | - pdata->gain << EXYNOS4_TMU_GAIN_SHIFT; - if (on) { - con |= EXYNOS4_TMU_CORE_ON; - interrupt_en = pdata->trigger_level3_en << 12 | - pdata->trigger_level2_en << 8 | - pdata->trigger_level1_en << 4 | - pdata->trigger_level0_en; - } else { - con |= EXYNOS4_TMU_CORE_OFF; - interrupt_en = 0; /* Disable all interrupts */ - } - writel(interrupt_en, data->base + EXYNOS4_TMU_REG_INTEN); - writel(con, data->base + EXYNOS4_TMU_REG_CONTROL); - - clk_disable(data->clk); - mutex_unlock(&data->lock); -} - -static int exynos4_tmu_read(struct exynos4_tmu_data *data) -{ - u8 temp_code; - int temp; - - mutex_lock(&data->lock); - clk_enable(data->clk); - - temp_code = readb(data->base + EXYNOS4_TMU_REG_CURRENT_TEMP); - temp = code_to_temp(data, temp_code); - - clk_disable(data->clk); - mutex_unlock(&data->lock); - - return temp; -} - -static void exynos4_tmu_work(struct work_struct *work) -{ - struct exynos4_tmu_data *data = container_of(work, - struct exynos4_tmu_data, irq_work); - - mutex_lock(&data->lock); - clk_enable(data->clk); - - writel(EXYNOS4_TMU_INTCLEAR_VAL, data->base + EXYNOS4_TMU_REG_INTCLEAR); - - kobject_uevent(&data->hwmon_dev->kobj, KOBJ_CHANGE); - - enable_irq(data->irq); - - clk_disable(data->clk); - mutex_unlock(&data->lock); -} - -static irqreturn_t exynos4_tmu_irq(int irq, void *id) -{ - struct exynos4_tmu_data *data = id; - - disable_irq_nosync(irq); - schedule_work(&data->irq_work); - - return IRQ_HANDLED; -} - -static ssize_t exynos4_tmu_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "exynos4-tmu\n"); -} - -static ssize_t exynos4_tmu_show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct exynos4_tmu_data *data = dev_get_drvdata(dev); - int ret; - - ret = exynos4_tmu_read(data); - if (ret < 0) - return ret; - - /* convert from degree Celsius to millidegree Celsius */ - return sprintf(buf, "%d\n", ret * 1000); -} - -static ssize_t exynos4_tmu_show_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct exynos4_tmu_data *data = dev_get_drvdata(dev); - struct exynos4_tmu_platform_data *pdata = data->pdata; - int temp; - unsigned int trigger_level; - - temp = exynos4_tmu_read(data); - if (temp < 0) - return temp; - - trigger_level = pdata->threshold + pdata->trigger_levels[attr->index]; - - return sprintf(buf, "%d\n", !!(temp > trigger_level)); -} - -static ssize_t exynos4_tmu_show_level(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct exynos4_tmu_data *data = dev_get_drvdata(dev); - struct exynos4_tmu_platform_data *pdata = data->pdata; - unsigned int temp = pdata->threshold + - pdata->trigger_levels[attr->index]; - - return sprintf(buf, "%u\n", temp * 1000); -} - -static DEVICE_ATTR(name, S_IRUGO, exynos4_tmu_show_name, NULL); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, exynos4_tmu_show_temp, NULL, 0); - -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, - exynos4_tmu_show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, - exynos4_tmu_show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, - exynos4_tmu_show_alarm, NULL, 3); - -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, exynos4_tmu_show_level, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, exynos4_tmu_show_level, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_emergency, S_IRUGO, - exynos4_tmu_show_level, NULL, 3); - -static struct attribute *exynos4_tmu_attributes[] = { - &dev_attr_name.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_emergency.dev_attr.attr, - NULL, -}; - -static const struct attribute_group exynos4_tmu_attr_group = { - .attrs = exynos4_tmu_attributes, -}; - -static int __devinit exynos4_tmu_probe(struct platform_device *pdev) -{ - struct exynos4_tmu_data *data; - struct exynos4_tmu_platform_data *pdata = pdev->dev.platform_data; - int ret; - - if (!pdata) { - dev_err(&pdev->dev, "No platform init data supplied.\n"); - return -ENODEV; - } - - data = kzalloc(sizeof(struct exynos4_tmu_data), GFP_KERNEL); - if (!data) { - dev_err(&pdev->dev, "Failed to allocate driver structure\n"); - return -ENOMEM; - } - - data->irq = platform_get_irq(pdev, 0); - if (data->irq < 0) { - ret = data->irq; - dev_err(&pdev->dev, "Failed to get platform irq\n"); - goto err_free; - } - - INIT_WORK(&data->irq_work, exynos4_tmu_work); - - data->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!data->mem) { - ret = -ENOENT; - dev_err(&pdev->dev, "Failed to get platform resource\n"); - goto err_free; - } - - data->mem = request_mem_region(data->mem->start, - resource_size(data->mem), pdev->name); - if (!data->mem) { - ret = -ENODEV; - dev_err(&pdev->dev, "Failed to request memory region\n"); - goto err_free; - } - - data->base = ioremap(data->mem->start, resource_size(data->mem)); - if (!data->base) { - ret = -ENODEV; - dev_err(&pdev->dev, "Failed to ioremap memory\n"); - goto err_mem_region; - } - - ret = request_irq(data->irq, exynos4_tmu_irq, - IRQF_TRIGGER_RISING, - "exynos4-tmu", data); - if (ret) { - dev_err(&pdev->dev, "Failed to request irq: %d\n", data->irq); - goto err_io_remap; - } - - data->clk = clk_get(NULL, "tmu_apbif"); - if (IS_ERR(data->clk)) { - ret = PTR_ERR(data->clk); - dev_err(&pdev->dev, "Failed to get clock\n"); - goto err_irq; - } - - data->pdata = pdata; - platform_set_drvdata(pdev, data); - mutex_init(&data->lock); - - ret = exynos4_tmu_initialize(pdev); - if (ret) { - dev_err(&pdev->dev, "Failed to initialize TMU\n"); - goto err_clk; - } - - ret = sysfs_create_group(&pdev->dev.kobj, &exynos4_tmu_attr_group); - if (ret) { - dev_err(&pdev->dev, "Failed to create sysfs group\n"); - goto err_clk; - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - dev_err(&pdev->dev, "Failed to register hwmon device\n"); - goto err_create_group; - } - - exynos4_tmu_control(pdev, true); - - return 0; - -err_create_group: - sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group); -err_clk: - platform_set_drvdata(pdev, NULL); - clk_put(data->clk); -err_irq: - free_irq(data->irq, data); -err_io_remap: - iounmap(data->base); -err_mem_region: - release_mem_region(data->mem->start, resource_size(data->mem)); -err_free: - kfree(data); - - return ret; -} - -static int __devexit exynos4_tmu_remove(struct platform_device *pdev) -{ - struct exynos4_tmu_data *data = platform_get_drvdata(pdev); - - exynos4_tmu_control(pdev, false); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &exynos4_tmu_attr_group); - - clk_put(data->clk); - - free_irq(data->irq, data); - - iounmap(data->base); - release_mem_region(data->mem->start, resource_size(data->mem)); - - platform_set_drvdata(pdev, NULL); - - kfree(data); - - return 0; -} - -#ifdef CONFIG_PM -static int exynos4_tmu_suspend(struct platform_device *pdev, pm_message_t state) -{ - exynos4_tmu_control(pdev, false); - - return 0; -} - -static int exynos4_tmu_resume(struct platform_device *pdev) -{ - exynos4_tmu_initialize(pdev); - exynos4_tmu_control(pdev, true); - - return 0; -} -#else -#define exynos4_tmu_suspend NULL -#define exynos4_tmu_resume NULL -#endif - -static struct platform_driver exynos4_tmu_driver = { - .driver = { - .name = "exynos4-tmu", - .owner = THIS_MODULE, - }, - .probe = exynos4_tmu_probe, - .remove = __devexit_p(exynos4_tmu_remove), - .suspend = exynos4_tmu_suspend, - .resume = exynos4_tmu_resume, -}; - -module_platform_driver(exynos4_tmu_driver); - -MODULE_DESCRIPTION("EXYNOS4 TMU Driver"); -MODULE_AUTHOR("Donggeun Kim "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:exynos4-tmu"); diff --git a/ANDROID_3.4.5/drivers/hwmon/f71805f.c b/ANDROID_3.4.5/drivers/hwmon/f71805f.c deleted file mode 100644 index 3e4da620..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/f71805f.c +++ /dev/null @@ -1,1669 +0,0 @@ -/* - * f71805f.c - driver for the Fintek F71805F/FG and F71872F/FG Super-I/O - * chips integrated hardware monitoring features - * Copyright (C) 2005-2006 Jean Delvare - * - * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates - * complete hardware monitoring features: voltage, fan and temperature - * sensors, and manual and automatic fan speed control. - * - * The F71872F/FG is almost the same, with two more voltages monitored, - * and 6 VID inputs. - * - * The F71806F/FG is essentially the same as the F71872F/FG. It even has - * the same chip ID, so the driver can't differentiate between. - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static struct platform_device *pdev; - -#define DRVNAME "f71805f" -enum kinds { f71805f, f71872f }; - -/* - * Super-I/O constants and functions - */ - -#define F71805F_LD_HWM 0x04 - -#define SIO_REG_LDSEL 0x07 /* Logical device select */ -#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ -#define SIO_REG_DEVREV 0x22 /* Device revision */ -#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ -#define SIO_REG_FNSEL1 0x29 /* Multi Function Select 1 (F71872F) */ -#define SIO_REG_ENABLE 0x30 /* Logical device enable */ -#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ - -#define SIO_FINTEK_ID 0x1934 -#define SIO_F71805F_ID 0x0406 -#define SIO_F71872F_ID 0x0341 - -static inline int -superio_inb(int base, int reg) -{ - outb(reg, base); - return inb(base + 1); -} - -static int -superio_inw(int base, int reg) -{ - int val; - outb(reg++, base); - val = inb(base + 1) << 8; - outb(reg, base); - val |= inb(base + 1); - return val; -} - -static inline void -superio_select(int base, int ld) -{ - outb(SIO_REG_LDSEL, base); - outb(ld, base + 1); -} - -static inline void -superio_enter(int base) -{ - outb(0x87, base); - outb(0x87, base); -} - -static inline void -superio_exit(int base) -{ - outb(0xaa, base); -} - -/* - * ISA constants - */ - -#define REGION_LENGTH 8 -#define ADDR_REG_OFFSET 5 -#define DATA_REG_OFFSET 6 - -/* - * Registers - */ - -/* in nr from 0 to 10 (8-bit values) */ -#define F71805F_REG_IN(nr) (0x10 + (nr)) -#define F71805F_REG_IN_HIGH(nr) ((nr) < 10 ? 0x40 + 2 * (nr) : 0x2E) -#define F71805F_REG_IN_LOW(nr) ((nr) < 10 ? 0x41 + 2 * (nr) : 0x2F) -/* fan nr from 0 to 2 (12-bit values, two registers) */ -#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr)) -#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr)) -#define F71805F_REG_FAN_TARGET(nr) (0x69 + 16 * (nr)) -#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr)) -#define F71805F_REG_PWM_FREQ(nr) (0x63 + 16 * (nr)) -#define F71805F_REG_PWM_DUTY(nr) (0x6B + 16 * (nr)) -/* temp nr from 0 to 2 (8-bit values) */ -#define F71805F_REG_TEMP(nr) (0x1B + (nr)) -#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr)) -#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr)) -#define F71805F_REG_TEMP_MODE 0x01 -/* pwm/fan pwmnr from 0 to 2, auto point apnr from 0 to 2 */ -/* map Fintek numbers to our numbers as follows: 9->0, 5->1, 1->2 */ -#define F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr) \ - (0xA0 + 0x10 * (pwmnr) + (2 - (apnr))) -#define F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr) \ - (0xA4 + 0x10 * (pwmnr) + \ - 2 * (2 - (apnr))) - -#define F71805F_REG_START 0x00 -/* status nr from 0 to 2 */ -#define F71805F_REG_STATUS(nr) (0x36 + (nr)) - -/* individual register bits */ -#define FAN_CTRL_DC_MODE 0x10 -#define FAN_CTRL_LATCH_FULL 0x08 -#define FAN_CTRL_MODE_MASK 0x03 -#define FAN_CTRL_MODE_SPEED 0x00 -#define FAN_CTRL_MODE_TEMPERATURE 0x01 -#define FAN_CTRL_MODE_MANUAL 0x02 - -/* - * Data structures and manipulation thereof - */ - -struct f71805f_auto_point { - u8 temp[3]; - u16 fan[3]; -}; - -struct f71805f_data { - unsigned short addr; - const char *name; - struct device *hwmon_dev; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - unsigned long last_limits; /* In jiffies */ - - /* Register values */ - u8 in[11]; - u8 in_high[11]; - u8 in_low[11]; - u16 has_in; - u16 fan[3]; - u16 fan_low[3]; - u16 fan_target[3]; - u8 fan_ctrl[3]; - u8 pwm[3]; - u8 pwm_freq[3]; - u8 temp[3]; - u8 temp_high[3]; - u8 temp_hyst[3]; - u8 temp_mode; - unsigned long alarms; - struct f71805f_auto_point auto_points[3]; -}; - -struct f71805f_sio_data { - enum kinds kind; - u8 fnsel1; -}; - -static inline long in_from_reg(u8 reg) -{ - return reg * 8; -} - -/* The 2 least significant bits are not used */ -static inline u8 in_to_reg(long val) -{ - if (val <= 0) - return 0; - if (val >= 2016) - return 0xfc; - return ((val + 16) / 32) << 2; -} - -/* in0 is downscaled by a factor 2 internally */ -static inline long in0_from_reg(u8 reg) -{ - return reg * 16; -} - -static inline u8 in0_to_reg(long val) -{ - if (val <= 0) - return 0; - if (val >= 4032) - return 0xfc; - return ((val + 32) / 64) << 2; -} - -/* The 4 most significant bits are not used */ -static inline long fan_from_reg(u16 reg) -{ - reg &= 0xfff; - if (!reg || reg == 0xfff) - return 0; - return 1500000 / reg; -} - -static inline u16 fan_to_reg(long rpm) -{ - /* - * If the low limit is set below what the chip can measure, - * store the largest possible 12-bit value in the registers, - * so that no alarm will ever trigger. - */ - if (rpm < 367) - return 0xfff; - return 1500000 / rpm; -} - -static inline unsigned long pwm_freq_from_reg(u8 reg) -{ - unsigned long clock = (reg & 0x80) ? 48000000UL : 1000000UL; - - reg &= 0x7f; - if (reg == 0) - reg++; - return clock / (reg << 8); -} - -static inline u8 pwm_freq_to_reg(unsigned long val) -{ - if (val >= 187500) /* The highest we can do */ - return 0x80; - if (val >= 1475) /* Use 48 MHz clock */ - return 0x80 | (48000000UL / (val << 8)); - if (val < 31) /* The lowest we can do */ - return 0x7f; - else /* Use 1 MHz clock */ - return 1000000UL / (val << 8); -} - -static inline int pwm_mode_from_reg(u8 reg) -{ - return !(reg & FAN_CTRL_DC_MODE); -} - -static inline long temp_from_reg(u8 reg) -{ - return reg * 1000; -} - -static inline u8 temp_to_reg(long val) -{ - if (val <= 0) - return 0; - if (val >= 1000 * 0xff) - return 0xff; - return (val + 500) / 1000; -} - -/* - * Device I/O access - */ - -/* Must be called with data->update_lock held, except during initialization */ -static u8 f71805f_read8(struct f71805f_data *data, u8 reg) -{ - outb(reg, data->addr + ADDR_REG_OFFSET); - return inb(data->addr + DATA_REG_OFFSET); -} - -/* Must be called with data->update_lock held, except during initialization */ -static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val) -{ - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val, data->addr + DATA_REG_OFFSET); -} - -/* - * It is important to read the MSB first, because doing so latches the - * value of the LSB, so we are sure both bytes belong to the same value. - * Must be called with data->update_lock held, except during initialization - */ -static u16 f71805f_read16(struct f71805f_data *data, u8 reg) -{ - u16 val; - - outb(reg, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET) << 8; - outb(++reg, data->addr + ADDR_REG_OFFSET); - val |= inb(data->addr + DATA_REG_OFFSET); - - return val; -} - -/* Must be called with data->update_lock held, except during initialization */ -static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val) -{ - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val >> 8, data->addr + DATA_REG_OFFSET); - outb(++reg, data->addr + ADDR_REG_OFFSET); - outb(val & 0xff, data->addr + DATA_REG_OFFSET); -} - -static struct f71805f_data *f71805f_update_device(struct device *dev) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - int nr, apnr; - - mutex_lock(&data->update_lock); - - /* Limit registers cache is refreshed after 60 seconds */ - if (time_after(jiffies, data->last_updated + 60 * HZ) - || !data->valid) { - for (nr = 0; nr < 11; nr++) { - if (!(data->has_in & (1 << nr))) - continue; - data->in_high[nr] = f71805f_read8(data, - F71805F_REG_IN_HIGH(nr)); - data->in_low[nr] = f71805f_read8(data, - F71805F_REG_IN_LOW(nr)); - } - for (nr = 0; nr < 3; nr++) { - data->fan_low[nr] = f71805f_read16(data, - F71805F_REG_FAN_LOW(nr)); - data->fan_target[nr] = f71805f_read16(data, - F71805F_REG_FAN_TARGET(nr)); - data->pwm_freq[nr] = f71805f_read8(data, - F71805F_REG_PWM_FREQ(nr)); - } - for (nr = 0; nr < 3; nr++) { - data->temp_high[nr] = f71805f_read8(data, - F71805F_REG_TEMP_HIGH(nr)); - data->temp_hyst[nr] = f71805f_read8(data, - F71805F_REG_TEMP_HYST(nr)); - } - data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE); - for (nr = 0; nr < 3; nr++) { - for (apnr = 0; apnr < 3; apnr++) { - data->auto_points[nr].temp[apnr] = - f71805f_read8(data, - F71805F_REG_PWM_AUTO_POINT_TEMP(nr, - apnr)); - data->auto_points[nr].fan[apnr] = - f71805f_read16(data, - F71805F_REG_PWM_AUTO_POINT_FAN(nr, - apnr)); - } - } - - data->last_limits = jiffies; - } - - /* Measurement registers cache is refreshed after 1 second */ - if (time_after(jiffies, data->last_updated + HZ) - || !data->valid) { - for (nr = 0; nr < 11; nr++) { - if (!(data->has_in & (1 << nr))) - continue; - data->in[nr] = f71805f_read8(data, - F71805F_REG_IN(nr)); - } - for (nr = 0; nr < 3; nr++) { - data->fan[nr] = f71805f_read16(data, - F71805F_REG_FAN(nr)); - data->fan_ctrl[nr] = f71805f_read8(data, - F71805F_REG_FAN_CTRL(nr)); - data->pwm[nr] = f71805f_read8(data, - F71805F_REG_PWM_DUTY(nr)); - } - for (nr = 0; nr < 3; nr++) { - data->temp[nr] = f71805f_read8(data, - F71805F_REG_TEMP(nr)); - } - data->alarms = f71805f_read8(data, F71805F_REG_STATUS(0)) - + (f71805f_read8(data, F71805F_REG_STATUS(1)) << 8) - + (f71805f_read8(data, F71805F_REG_STATUS(2)) << 16); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Sysfs interface - */ - -static ssize_t show_in0(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", in0_from_reg(data->in[nr])); -} - -static ssize_t show_in0_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[nr])); -} - -static ssize_t show_in0_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[nr])); -} - -static ssize_t set_in0_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_high[nr] = in0_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_in0_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_low[nr] = in0_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_in(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", in_from_reg(data->in[nr])); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr])); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr])); -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_high[nr] = in_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_low[nr] = in_to_reg(val); - f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr])); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr])); -} - -static ssize_t show_fan_target(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", fan_from_reg(data->fan_target[nr])); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_low[nr] = fan_to_reg(val); - f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_fan_target(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_target[nr] = fan_to_reg(val); - f71805f_write16(data, F71805F_REG_FAN_TARGET(nr), - data->fan_target[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%d\n", (int)data->pwm[nr]); -} - -static ssize_t show_pwm_enable(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - int mode; - - switch (data->fan_ctrl[nr] & FAN_CTRL_MODE_MASK) { - case FAN_CTRL_MODE_SPEED: - mode = 3; - break; - case FAN_CTRL_MODE_TEMPERATURE: - mode = 2; - break; - default: /* MANUAL */ - mode = 1; - } - - return sprintf(buf, "%d\n", mode); -} - -static ssize_t show_pwm_freq(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%lu\n", pwm_freq_from_reg(data->pwm_freq[nr])); -} - -static ssize_t show_pwm_mode(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%d\n", pwm_mode_from_reg(data->fan_ctrl[nr])); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val > 255) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm[nr] = val; - f71805f_write8(data, F71805F_REG_PWM_DUTY(nr), data->pwm[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static struct attribute *f71805f_attr_pwm[]; - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val < 1 || val > 3) - return -EINVAL; - - if (val > 1) { /* Automatic mode, user can't set PWM value */ - if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr], - S_IRUGO)) - dev_dbg(dev, "chmod -w pwm%d failed\n", nr + 1); - } - - mutex_lock(&data->update_lock); - reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(nr)) - & ~FAN_CTRL_MODE_MASK; - switch (val) { - case 1: - reg |= FAN_CTRL_MODE_MANUAL; - break; - case 2: - reg |= FAN_CTRL_MODE_TEMPERATURE; - break; - case 3: - reg |= FAN_CTRL_MODE_SPEED; - break; - } - data->fan_ctrl[nr] = reg; - f71805f_write8(data, F71805F_REG_FAN_CTRL(nr), reg); - mutex_unlock(&data->update_lock); - - if (val == 1) { /* Manual mode, user can set PWM value */ - if (sysfs_chmod_file(&dev->kobj, f71805f_attr_pwm[nr], - S_IRUGO | S_IWUSR)) - dev_dbg(dev, "chmod +w pwm%d failed\n", nr + 1); - } - - return count; -} - -static ssize_t set_pwm_freq(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm_freq[nr] = pwm_freq_to_reg(val); - f71805f_write8(data, F71805F_REG_PWM_FREQ(nr), data->pwm_freq[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_auto_point_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - int pwmnr = attr->nr; - int apnr = attr->index; - - return sprintf(buf, "%ld\n", - temp_from_reg(data->auto_points[pwmnr].temp[apnr])); -} - -static ssize_t set_pwm_auto_point_temp(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - int pwmnr = attr->nr; - int apnr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val); - f71805f_write8(data, F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr), - data->auto_points[pwmnr].temp[apnr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_auto_point_fan(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - int pwmnr = attr->nr; - int apnr = attr->index; - - return sprintf(buf, "%ld\n", - fan_from_reg(data->auto_points[pwmnr].fan[apnr])); -} - -static ssize_t set_pwm_auto_point_fan(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - int pwmnr = attr->nr; - int apnr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val); - f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr), - data->auto_points[pwmnr].fan[apnr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr])); -} - -static ssize_t show_temp_hyst(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr])); -} - -static ssize_t show_temp_type(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - - /* 3 is diode, 4 is thermistor */ - return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_high[nr] = temp_to_reg(val); - f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_temp_hyst(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_hyst[nr] = temp_to_reg(val); - f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_alarms_in(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - - return sprintf(buf, "%lu\n", data->alarms & 0x7ff); -} - -static ssize_t show_alarms_fan(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - - return sprintf(buf, "%lu\n", (data->alarms >> 16) & 0x07); -} - -static ssize_t show_alarms_temp(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - - return sprintf(buf, "%lu\n", (data->alarms >> 11) & 0x07); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = f71805f_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int bitnr = attr->index; - - return sprintf(buf, "%lu\n", (data->alarms >> bitnr) & 1); -} - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71805f_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0); -static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, - show_in0_max, set_in0_max, 0); -static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, - show_in0_min, set_in0_min, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 1); -static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 2); -static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 3); -static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); -static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 4); -static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5); -static SENSOR_DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 5); -static SENSOR_DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6); -static SENSOR_DEVICE_ATTR(in6_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 6); -static SENSOR_DEVICE_ATTR(in6_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7); -static SENSOR_DEVICE_ATTR(in7_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 7); -static SENSOR_DEVICE_ATTR(in7_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8); -static SENSOR_DEVICE_ATTR(in8_max, S_IRUGO | S_IWUSR, - show_in_max, set_in_max, 8); -static SENSOR_DEVICE_ATTR(in8_min, S_IRUGO | S_IWUSR, - show_in_min, set_in_min, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in0, NULL, 9); -static SENSOR_DEVICE_ATTR(in9_max, S_IRUGO | S_IWUSR, - show_in0_max, set_in0_max, 9); -static SENSOR_DEVICE_ATTR(in9_min, S_IRUGO | S_IWUSR, - show_in0_min, set_in0_min, 9); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in0, NULL, 10); -static SENSOR_DEVICE_ATTR(in10_max, S_IRUGO | S_IWUSR, - show_in0_max, set_in0_max, 10); -static SENSOR_DEVICE_ATTR(in10_min, S_IRUGO | S_IWUSR, - show_in0_min, set_in0_min, 10); - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, - show_fan_target, set_fan_target, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO | S_IWUSR, - show_fan_target, set_fan_target, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, - show_fan_min, set_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan3_target, S_IRUGO | S_IWUSR, - show_fan_target, set_fan_target, 2); - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - show_temp_hyst, set_temp_hyst, 0); -static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, - show_temp_hyst, set_temp_hyst, 1); -static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 2); -static SENSOR_DEVICE_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, - show_temp_hyst, set_temp_hyst, 2); -static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); - -/* - * pwm (value) files are created read-only, write permission is - * then added or removed dynamically as needed - */ -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, - show_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO | S_IWUSR, - show_pwm_freq, set_pwm_freq, 0); -static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, - show_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO | S_IWUSR, - show_pwm_freq, set_pwm_freq, 1); -static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, show_pwm_mode, NULL, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO, show_pwm, set_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO | S_IWUSR, - show_pwm_enable, set_pwm_enable, 2); -static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR, - show_pwm_freq, set_pwm_freq, 2); -static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2); - -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 0, 0); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 0, 0); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 0, 1); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 0, 1); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 0, 2); -static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 0, 2); - -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 1, 0); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 1, 0); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 1, 1); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 1, 1); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 1, 2); -static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 1, 2); - -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 2, 0); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 2, 0); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 2, 1); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 2, 1); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR, - show_pwm_auto_point_temp, set_pwm_auto_point_temp, - 2, 2); -static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_fan, S_IRUGO | S_IWUSR, - show_pwm_auto_point_fan, set_pwm_auto_point_fan, - 2, 2); - -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(temp1_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 16); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 17); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 18); -static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL); -static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL); -static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL); - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *f71805f_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_target.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_target.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_target.dev_attr.attr, - - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_mode.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_mode.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_mode.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_type.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_type.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_type.dev_attr.attr, - - &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_fan.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_fan.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_fan.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_fan.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_fan.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point3_fan.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_fan.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_fan.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point3_fan.dev_attr.attr, - - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - &dev_attr_alarms_in.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &dev_attr_alarms_temp.attr, - &dev_attr_alarms_fan.attr, - - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group f71805f_group = { - .attrs = f71805f_attributes, -}; - -static struct attribute *f71805f_attributes_optin[4][5] = { - { - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in8_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in9_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in10_max.dev_attr.attr, - &sensor_dev_attr_in10_min.dev_attr.attr, - &sensor_dev_attr_in10_alarm.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group f71805f_group_optin[4] = { - { .attrs = f71805f_attributes_optin[0] }, - { .attrs = f71805f_attributes_optin[1] }, - { .attrs = f71805f_attributes_optin[2] }, - { .attrs = f71805f_attributes_optin[3] }, -}; - -/* - * We don't include pwm_freq files in the arrays above, because they must be - * created conditionally (only if pwm_mode is 1 == PWM) - */ -static struct attribute *f71805f_attributes_pwm_freq[] = { - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - NULL -}; - -static const struct attribute_group f71805f_group_pwm_freq = { - .attrs = f71805f_attributes_pwm_freq, -}; - -/* We also need an indexed access to pwmN files to toggle writability */ -static struct attribute *f71805f_attr_pwm[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, -}; - -/* - * Device registration and initialization - */ - -static void __devinit f71805f_init_device(struct f71805f_data *data) -{ - u8 reg; - int i; - - reg = f71805f_read8(data, F71805F_REG_START); - if ((reg & 0x41) != 0x01) { - printk(KERN_DEBUG DRVNAME ": Starting monitoring " - "operations\n"); - f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40); - } - - /* - * Fan monitoring can be disabled. If it is, we won't be polling - * the register values, and won't create the related sysfs files. - */ - for (i = 0; i < 3; i++) { - data->fan_ctrl[i] = f71805f_read8(data, - F71805F_REG_FAN_CTRL(i)); - /* - * Clear latch full bit, else "speed mode" fan speed control - * doesn't work - */ - if (data->fan_ctrl[i] & FAN_CTRL_LATCH_FULL) { - data->fan_ctrl[i] &= ~FAN_CTRL_LATCH_FULL; - f71805f_write8(data, F71805F_REG_FAN_CTRL(i), - data->fan_ctrl[i]); - } - } -} - -static int __devinit f71805f_probe(struct platform_device *pdev) -{ - struct f71805f_sio_data *sio_data = pdev->dev.platform_data; - struct f71805f_data *data; - struct resource *res; - int i, err; - - static const char * const names[] = { - "f71805f", - "f71872f", - }; - - data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - pr_err("Out of memory\n"); - goto exit; - } - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) { - err = -EBUSY; - dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)(res->start + ADDR_REG_OFFSET), - (unsigned long)(res->start + ADDR_REG_OFFSET + 1)); - goto exit_free; - } - data->addr = res->start; - data->name = names[sio_data->kind]; - mutex_init(&data->update_lock); - - platform_set_drvdata(pdev, data); - - /* Some voltage inputs depend on chip model and configuration */ - switch (sio_data->kind) { - case f71805f: - data->has_in = 0x1ff; - break; - case f71872f: - data->has_in = 0x6ef; - if (sio_data->fnsel1 & 0x01) - data->has_in |= (1 << 4); /* in4 */ - if (sio_data->fnsel1 & 0x02) - data->has_in |= (1 << 8); /* in8 */ - break; - } - - /* Initialize the F71805F chip */ - f71805f_init_device(data); - - /* Register sysfs interface files */ - err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group); - if (err) - goto exit_release_region; - if (data->has_in & (1 << 4)) { /* in4 */ - err = sysfs_create_group(&pdev->dev.kobj, - &f71805f_group_optin[0]); - if (err) - goto exit_remove_files; - } - if (data->has_in & (1 << 8)) { /* in8 */ - err = sysfs_create_group(&pdev->dev.kobj, - &f71805f_group_optin[1]); - if (err) - goto exit_remove_files; - } - if (data->has_in & (1 << 9)) { /* in9 (F71872F/FG only) */ - err = sysfs_create_group(&pdev->dev.kobj, - &f71805f_group_optin[2]); - if (err) - goto exit_remove_files; - } - if (data->has_in & (1 << 10)) { /* in9 (F71872F/FG only) */ - err = sysfs_create_group(&pdev->dev.kobj, - &f71805f_group_optin[3]); - if (err) - goto exit_remove_files; - } - for (i = 0; i < 3; i++) { - /* If control mode is PWM, create pwm_freq file */ - if (!(data->fan_ctrl[i] & FAN_CTRL_DC_MODE)) { - err = sysfs_create_file(&pdev->dev.kobj, - f71805f_attributes_pwm_freq[i]); - if (err) - goto exit_remove_files; - } - /* If PWM is in manual mode, add write permission */ - if (data->fan_ctrl[i] & FAN_CTRL_MODE_MANUAL) { - err = sysfs_chmod_file(&pdev->dev.kobj, - f71805f_attr_pwm[i], - S_IRUGO | S_IWUSR); - if (err) { - dev_err(&pdev->dev, "chmod +w pwm%d failed\n", - i + 1); - goto exit_remove_files; - } - } - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - dev_err(&pdev->dev, "Class registration failed (%d)\n", err); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); - for (i = 0; i < 4; i++) - sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); - sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); -exit_release_region: - release_region(res->start + ADDR_REG_OFFSET, 2); -exit_free: - platform_set_drvdata(pdev, NULL); - kfree(data); -exit: - return err; -} - -static int __devexit f71805f_remove(struct platform_device *pdev) -{ - struct f71805f_data *data = platform_get_drvdata(pdev); - struct resource *res; - int i; - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &f71805f_group); - for (i = 0; i < 4; i++) - sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]); - sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq); - platform_set_drvdata(pdev, NULL); - kfree(data); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start + ADDR_REG_OFFSET, 2); - - return 0; -} - -static struct platform_driver f71805f_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = f71805f_probe, - .remove = __devexit_p(f71805f_remove), -}; - -static int __init f71805f_device_add(unsigned short address, - const struct f71805f_sio_data *sio_data) -{ - struct resource res = { - .start = address, - .end = address + REGION_LENGTH - 1, - .flags = IORESOURCE_IO, - }; - int err; - - pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - res.name = pdev->name; - 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; - } - - err = platform_device_add_data(pdev, sio_data, - sizeof(struct f71805f_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init f71805f_find(int sioaddr, unsigned short *address, - struct f71805f_sio_data *sio_data) -{ - int err = -ENODEV; - u16 devid; - - static const char * const names[] = { - "F71805F/FG", - "F71872F/FG or F71806F/FG", - }; - - superio_enter(sioaddr); - - devid = superio_inw(sioaddr, SIO_REG_MANID); - if (devid != SIO_FINTEK_ID) - goto exit; - - devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); - switch (devid) { - case SIO_F71805F_ID: - sio_data->kind = f71805f; - break; - case SIO_F71872F_ID: - sio_data->kind = f71872f; - sio_data->fnsel1 = superio_inb(sioaddr, SIO_REG_FNSEL1); - break; - default: - pr_info("Unsupported Fintek device, skipping\n"); - goto exit; - } - - superio_select(sioaddr, F71805F_LD_HWM); - if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - pr_warn("Device not activated, skipping\n"); - goto exit; - } - - *address = superio_inw(sioaddr, SIO_REG_ADDR); - if (*address == 0) { - pr_warn("Base address not set, skipping\n"); - goto exit; - } - *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ - - err = 0; - pr_info("Found %s chip at %#x, revision %u\n", - names[sio_data->kind], *address, - superio_inb(sioaddr, SIO_REG_DEVREV)); - -exit: - superio_exit(sioaddr); - return err; -} - -static int __init f71805f_init(void) -{ - int err; - unsigned short address; - struct f71805f_sio_data sio_data; - - if (f71805f_find(0x2e, &address, &sio_data) - && f71805f_find(0x4e, &address, &sio_data)) - return -ENODEV; - - err = platform_driver_register(&f71805f_driver); - if (err) - goto exit; - - /* Sets global pdev as a side effect */ - err = f71805f_device_add(address, &sio_data); - if (err) - goto exit_driver; - - return 0; - -exit_driver: - platform_driver_unregister(&f71805f_driver); -exit: - return err; -} - -static void __exit f71805f_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&f71805f_driver); -} - -MODULE_AUTHOR("Jean Delvare "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("F71805F/F71872F hardware monitoring driver"); - -module_init(f71805f_init); -module_exit(f71805f_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/f71882fg.c b/ANDROID_3.4.5/drivers/hwmon/f71882fg.c deleted file mode 100644 index 6d122636..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/f71882fg.c +++ /dev/null @@ -1,2708 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 by Hans Edgington * - * Copyright (C) 2007-2011 Hans de Goede * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "f71882fg" - -#define SIO_F71858FG_LD_HWM 0x02 /* Hardware monitor logical device */ -#define SIO_F71882FG_LD_HWM 0x04 /* Hardware monitor logical device */ -#define SIO_UNLOCK_KEY 0x87 /* Key to enable Super-I/O */ -#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ - -#define SIO_REG_LDSEL 0x07 /* Logical device select */ -#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */ -#define SIO_REG_DEVREV 0x22 /* Device revision */ -#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */ -#define SIO_REG_ENABLE 0x30 /* Logical device enable */ -#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */ - -#define SIO_FINTEK_ID 0x1934 /* Manufacturers ID */ -#define SIO_F71808E_ID 0x0901 /* Chipset ID */ -#define SIO_F71808A_ID 0x1001 /* Chipset ID */ -#define SIO_F71858_ID 0x0507 /* Chipset ID */ -#define SIO_F71862_ID 0x0601 /* Chipset ID */ -#define SIO_F71869_ID 0x0814 /* Chipset ID */ -#define SIO_F71869A_ID 0x1007 /* Chipset ID */ -#define SIO_F71882_ID 0x0541 /* Chipset ID */ -#define SIO_F71889_ID 0x0723 /* Chipset ID */ -#define SIO_F71889E_ID 0x0909 /* Chipset ID */ -#define SIO_F71889A_ID 0x1005 /* Chipset ID */ -#define SIO_F8000_ID 0x0581 /* Chipset ID */ -#define SIO_F81865_ID 0x0704 /* Chipset ID */ - -#define REGION_LENGTH 8 -#define ADDR_REG_OFFSET 5 -#define DATA_REG_OFFSET 6 - -#define F71882FG_REG_IN_STATUS 0x12 /* f7188x only */ -#define F71882FG_REG_IN_BEEP 0x13 /* f7188x only */ -#define F71882FG_REG_IN(nr) (0x20 + (nr)) -#define F71882FG_REG_IN1_HIGH 0x32 /* f7188x only */ - -#define F71882FG_REG_FAN(nr) (0xA0 + (16 * (nr))) -#define F71882FG_REG_FAN_TARGET(nr) (0xA2 + (16 * (nr))) -#define F71882FG_REG_FAN_FULL_SPEED(nr) (0xA4 + (16 * (nr))) -#define F71882FG_REG_FAN_STATUS 0x92 -#define F71882FG_REG_FAN_BEEP 0x93 - -#define F71882FG_REG_TEMP(nr) (0x70 + 2 * (nr)) -#define F71882FG_REG_TEMP_OVT(nr) (0x80 + 2 * (nr)) -#define F71882FG_REG_TEMP_HIGH(nr) (0x81 + 2 * (nr)) -#define F71882FG_REG_TEMP_STATUS 0x62 -#define F71882FG_REG_TEMP_BEEP 0x63 -#define F71882FG_REG_TEMP_CONFIG 0x69 -#define F71882FG_REG_TEMP_HYST(nr) (0x6C + (nr)) -#define F71882FG_REG_TEMP_TYPE 0x6B -#define F71882FG_REG_TEMP_DIODE_OPEN 0x6F - -#define F71882FG_REG_PWM(nr) (0xA3 + (16 * (nr))) -#define F71882FG_REG_PWM_TYPE 0x94 -#define F71882FG_REG_PWM_ENABLE 0x96 - -#define F71882FG_REG_FAN_HYST(nr) (0x98 + (nr)) - -#define F71882FG_REG_FAN_FAULT_T 0x9F -#define F71882FG_FAN_NEG_TEMP_EN 0x20 -#define F71882FG_FAN_PROG_SEL 0x80 - -#define F71882FG_REG_POINT_PWM(pwm, point) (0xAA + (point) + (16 * (pwm))) -#define F71882FG_REG_POINT_TEMP(pwm, point) (0xA6 + (point) + (16 * (pwm))) -#define F71882FG_REG_POINT_MAPPING(nr) (0xAF + 16 * (nr)) - -#define F71882FG_REG_START 0x01 - -#define F71882FG_MAX_INS 9 - -#define FAN_MIN_DETECT 366 /* Lowest detectable fanspeed */ - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -enum chips { f71808e, f71808a, f71858fg, f71862fg, f71869, f71869a, f71882fg, - f71889fg, f71889ed, f71889a, f8000, f81865f }; - -static const char *const f71882fg_names[] = { - "f71808e", - "f71808a", - "f71858fg", - "f71862fg", - "f71869", /* Both f71869f and f71869e, reg. compatible and same id */ - "f71869a", - "f71882fg", - "f71889fg", /* f81801u too, same id */ - "f71889ed", - "f71889a", - "f8000", - "f81865f", -}; - -static const char f71882fg_has_in[][F71882FG_MAX_INS] = { - [f71808e] = { 1, 1, 1, 1, 1, 1, 0, 1, 1 }, - [f71808a] = { 1, 1, 1, 1, 0, 0, 0, 1, 1 }, - [f71858fg] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, - [f71862fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f71869] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f71869a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f71882fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f71889fg] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f71889ed] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f71889a] = { 1, 1, 1, 1, 1, 1, 1, 1, 1 }, - [f8000] = { 1, 1, 1, 0, 0, 0, 0, 0, 0 }, - [f81865f] = { 1, 1, 1, 1, 1, 1, 1, 0, 0 }, -}; - -static const char f71882fg_has_in1_alarm[] = { - [f71808e] = 0, - [f71808a] = 0, - [f71858fg] = 0, - [f71862fg] = 0, - [f71869] = 0, - [f71869a] = 0, - [f71882fg] = 1, - [f71889fg] = 1, - [f71889ed] = 1, - [f71889a] = 1, - [f8000] = 0, - [f81865f] = 1, -}; - -static const char f71882fg_fan_has_beep[] = { - [f71808e] = 0, - [f71808a] = 0, - [f71858fg] = 0, - [f71862fg] = 1, - [f71869] = 1, - [f71869a] = 1, - [f71882fg] = 1, - [f71889fg] = 1, - [f71889ed] = 1, - [f71889a] = 1, - [f8000] = 0, - [f81865f] = 1, -}; - -static const char f71882fg_nr_fans[] = { - [f71808e] = 3, - [f71808a] = 2, /* +1 fan which is monitor + simple pwm only */ - [f71858fg] = 3, - [f71862fg] = 3, - [f71869] = 3, - [f71869a] = 3, - [f71882fg] = 4, - [f71889fg] = 3, - [f71889ed] = 3, - [f71889a] = 3, - [f8000] = 3, /* +1 fan which is monitor only */ - [f81865f] = 2, -}; - -static const char f71882fg_temp_has_beep[] = { - [f71808e] = 0, - [f71808a] = 1, - [f71858fg] = 0, - [f71862fg] = 1, - [f71869] = 1, - [f71869a] = 1, - [f71882fg] = 1, - [f71889fg] = 1, - [f71889ed] = 1, - [f71889a] = 1, - [f8000] = 0, - [f81865f] = 1, -}; - -static const char f71882fg_nr_temps[] = { - [f71808e] = 2, - [f71808a] = 2, - [f71858fg] = 3, - [f71862fg] = 3, - [f71869] = 3, - [f71869a] = 3, - [f71882fg] = 3, - [f71889fg] = 3, - [f71889ed] = 3, - [f71889a] = 3, - [f8000] = 3, - [f81865f] = 2, -}; - -static struct platform_device *f71882fg_pdev; - -/* Super-I/O Function prototypes */ -static inline int superio_inb(int base, int reg); -static inline int superio_inw(int base, int reg); -static inline int superio_enter(int base); -static inline void superio_select(int base, int ld); -static inline void superio_exit(int base); - -struct f71882fg_sio_data { - enum chips type; -}; - -struct f71882fg_data { - unsigned short addr; - enum chips type; - struct device *hwmon_dev; - - struct mutex update_lock; - int temp_start; /* temp numbering start (0 or 1) */ - char valid; /* !=0 if following fields are valid */ - char auto_point_temp_signed; - unsigned long last_updated; /* In jiffies */ - unsigned long last_limits; /* In jiffies */ - - /* Register Values */ - u8 in[F71882FG_MAX_INS]; - u8 in1_max; - u8 in_status; - u8 in_beep; - u16 fan[4]; - u16 fan_target[4]; - u16 fan_full_speed[4]; - u8 fan_status; - u8 fan_beep; - /* - * Note: all models have max 3 temperature channels, but on some - * they are addressed as 0-2 and on others as 1-3, so for coding - * convenience we reserve space for 4 channels - */ - u16 temp[4]; - u8 temp_ovt[4]; - u8 temp_high[4]; - u8 temp_hyst[2]; /* 2 hysts stored per reg */ - u8 temp_type[4]; - u8 temp_status; - u8 temp_beep; - u8 temp_diode_open; - u8 temp_config; - u8 pwm[4]; - u8 pwm_enable; - u8 pwm_auto_point_hyst[2]; - u8 pwm_auto_point_mapping[4]; - u8 pwm_auto_point_pwm[4][5]; - s8 pwm_auto_point_temp[4][4]; -}; - -/* Sysfs in */ -static ssize_t show_in(struct device *dev, struct device_attribute *devattr, - char *buf); -static ssize_t show_in_max(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_in_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_in_beep(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_in_beep(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_in_alarm(struct device *dev, struct device_attribute - *devattr, char *buf); -/* Sysfs Fan */ -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf); -static ssize_t show_fan_full_speed(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_fan_full_speed(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_fan_beep(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_fan_beep(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf); -/* Sysfs Temp */ -static ssize_t show_temp(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_temp_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_temp_crit(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_temp_crit(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t show_temp_type(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t show_temp_beep(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t store_temp_beep(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count); -static ssize_t show_temp_alarm(struct device *dev, struct device_attribute - *devattr, char *buf); -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf); -/* PWM and Auto point control */ -static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, - char *buf); -static ssize_t store_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count); -static ssize_t show_simple_pwm(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_simple_pwm(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_pwm_enable(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_pwm_interpolate(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_pwm_interpolate(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_pwm_auto_point_channel(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_pwm_auto_point_channel(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_pwm_auto_point_pwm(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_pwm_auto_point_pwm(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -static ssize_t show_pwm_auto_point_temp(struct device *dev, - struct device_attribute *devattr, char *buf); -static ssize_t store_pwm_auto_point_temp(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count); -/* Sysfs misc */ -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf); - -static int __devinit f71882fg_probe(struct platform_device *pdev); -static int f71882fg_remove(struct platform_device *pdev); - -static struct platform_driver f71882fg_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = f71882fg_probe, - .remove = f71882fg_remove, -}; - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -/* - * Temp attr for the f71858fg, the f71858fg is special as it has its - * temperature indexes start at 0 (the others start at 1) - */ -static struct sensor_device_attribute_2 f71858fg_temp_attr[] = { - SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), - SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 0), - SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 0), - SENSOR_ATTR_2(temp1_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 0), - SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 0), - SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 0), - SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4), - SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0), - SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), - SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 1), - SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 1), - SENSOR_ATTR_2(temp2_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), - SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 1), - SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 1), - SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), - SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), - SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), - SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 2), - SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 2), - SENSOR_ATTR_2(temp3_max_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), - SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 2), - SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 2), - SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), - SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), -}; - -/* Temp attr for the standard models */ -static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { { - SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1), - SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 1), - SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 1), - /* - * Should really be temp1_max_alarm, but older versions did not handle - * the max and crit alarms separately and lm_sensors v2 depends on the - * presence of temp#_alarm files. The same goes for temp2/3 _alarm. - */ - SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1), - SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 1), - SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 1), - SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), - SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1), - SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), -}, { - SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2), - SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 2), - SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 2), - /* Should be temp2_max_alarm, see temp1_alarm note */ - SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2), - SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 2), - SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 2), - SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), - SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2), - SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), -}, { - SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3), - SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 3), - SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0, 3), - /* Should be temp3_max_alarm, see temp1_alarm note */ - SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3), - SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 3), - SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, - 0, 3), - SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7), - SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3), - SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3), -} }; - -/* Temp attr for models which can beep on temp alarm */ -static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { { - SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 1), - SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 5), -}, { - SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 2), - SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 6), -}, { - SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 3), - SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep, - store_temp_beep, 0, 7), -} }; - -/* - * Temp attr for the f8000 - * Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max) - * is used as hysteresis value to clear alarms - * Also like the f71858fg its temperature indexes start at 0 - */ -static struct sensor_device_attribute_2 f8000_temp_attr[] = { - SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0), - SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 0), - SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 0), - SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 4), - SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 0), - SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1), - SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 1), - SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 1), - SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5), - SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 1), - SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 2), - SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_crit, - store_temp_crit, 0, 2), - SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO|S_IWUSR, show_temp_max, - store_temp_max, 0, 2), - SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6), - SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2), -}; - -/* in attr for all models */ -static struct sensor_device_attribute_2 fxxxx_in_attr[] = { - SENSOR_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, 0), - SENSOR_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 0, 1), - SENSOR_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 0, 2), - SENSOR_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 0, 3), - SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4), - SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5), - SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6), - SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7), - SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8), -}; - -/* For models with in1 alarm capability */ -static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = { - SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max, - 0, 1), - SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep, - 0, 1), - SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1), -}; - -/* Fan / PWM attr common to all models */ -static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { { - SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0), - SENSOR_ATTR_2(fan1_full_speed, S_IRUGO|S_IWUSR, - show_fan_full_speed, - store_fan_full_speed, 0, 0), - SENSOR_ATTR_2(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 0), - SENSOR_ATTR_2(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 0), - SENSOR_ATTR_2(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 0), - SENSOR_ATTR_2(pwm1_interpolate, S_IRUGO|S_IWUSR, - show_pwm_interpolate, store_pwm_interpolate, 0, 0), -}, { - SENSOR_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 0, 1), - SENSOR_ATTR_2(fan2_full_speed, S_IRUGO|S_IWUSR, - show_fan_full_speed, - store_fan_full_speed, 0, 1), - SENSOR_ATTR_2(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 1), - SENSOR_ATTR_2(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 1), - SENSOR_ATTR_2(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 1), - SENSOR_ATTR_2(pwm2_interpolate, S_IRUGO|S_IWUSR, - show_pwm_interpolate, store_pwm_interpolate, 0, 1), -}, { - SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), - SENSOR_ATTR_2(fan3_full_speed, S_IRUGO|S_IWUSR, - show_fan_full_speed, - store_fan_full_speed, 0, 2), - SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), - SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 2), - SENSOR_ATTR_2(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 2), - SENSOR_ATTR_2(pwm3_interpolate, S_IRUGO|S_IWUSR, - show_pwm_interpolate, store_pwm_interpolate, 0, 2), -}, { - SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), - SENSOR_ATTR_2(fan4_full_speed, S_IRUGO|S_IWUSR, - show_fan_full_speed, - store_fan_full_speed, 0, 3), - SENSOR_ATTR_2(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 3), - SENSOR_ATTR_2(pwm4, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0, 3), - SENSOR_ATTR_2(pwm4_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0, 3), - SENSOR_ATTR_2(pwm4_interpolate, S_IRUGO|S_IWUSR, - show_pwm_interpolate, store_pwm_interpolate, 0, 3), -} }; - -/* Attr for the third fan of the f71808a, which only has manual pwm */ -static struct sensor_device_attribute_2 f71808a_fan3_attr[] = { - SENSOR_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 0, 2), - SENSOR_ATTR_2(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 0, 2), - SENSOR_ATTR_2(pwm3, S_IRUGO|S_IWUSR, - show_simple_pwm, store_simple_pwm, 0, 2), -}; - -/* Attr for models which can beep on Fan alarm */ -static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = { - SENSOR_ATTR_2(fan1_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 0), - SENSOR_ATTR_2(fan2_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 1), - SENSOR_ATTR_2(fan3_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 2), - SENSOR_ATTR_2(fan4_beep, S_IRUGO|S_IWUSR, show_fan_beep, - store_fan_beep, 0, 3), -}; - -/* - * PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the - * standard models - */ -static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { { - SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 0), - SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 0), - SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 0), - SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 0), - SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 0), -}, { - SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 1), - SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 1), - SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 1), - SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 1), - SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 1), -}, { - SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 2), - SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 2), - SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 2), - SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 2), - SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 2), -} }; - -/* - * PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the - * pwm setting when the temperature is above the pwmX_auto_point1_temp can be - * programmed instead of being hardcoded to 0xff - */ -static struct sensor_device_attribute_2 f71869_auto_pwm_attr[3][8] = { { - SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 0), - SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 0), - SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 0), - SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 0), - SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 0), -}, { - SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 1), - SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 1), - SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 1), - SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 1), - SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 1), -}, { - SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 2), - SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 2), - SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 2), - SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 2), - SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 2), -} }; - -/* PWM attr for the standard models */ -static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { { - SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 0), - SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 0), - SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 0), - SENSOR_ATTR_2(pwm1_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 0), - SENSOR_ATTR_2(pwm1_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 0), - SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 0), - SENSOR_ATTR_2(pwm1_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 0), - SENSOR_ATTR_2(pwm1_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 0), - SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 0), - SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 0), - SENSOR_ATTR_2(pwm1_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 0), - SENSOR_ATTR_2(pwm1_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 0), -}, { - SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 1), - SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 1), - SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 1), - SENSOR_ATTR_2(pwm2_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 1), - SENSOR_ATTR_2(pwm2_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 1), - SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 1), - SENSOR_ATTR_2(pwm2_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 1), - SENSOR_ATTR_2(pwm2_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 1), - SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 1), - SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 1), - SENSOR_ATTR_2(pwm2_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 1), - SENSOR_ATTR_2(pwm2_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 1), -}, { - SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 2), - SENSOR_ATTR_2(pwm3_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 2), - SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 2), - SENSOR_ATTR_2(pwm3_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 2), - SENSOR_ATTR_2(pwm3_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 2), - SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 2), - SENSOR_ATTR_2(pwm3_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 2), - SENSOR_ATTR_2(pwm3_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 2), - SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 2), - SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 2), - SENSOR_ATTR_2(pwm3_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 2), - SENSOR_ATTR_2(pwm3_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 2), -}, { - SENSOR_ATTR_2(pwm4_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 3), - SENSOR_ATTR_2(pwm4_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 3), - SENSOR_ATTR_2(pwm4_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 3), - SENSOR_ATTR_2(pwm4_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 3), - SENSOR_ATTR_2(pwm4_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 3), - SENSOR_ATTR_2(pwm4_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 3), - SENSOR_ATTR_2(pwm4_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 3), - SENSOR_ATTR_2(pwm4_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 3), - SENSOR_ATTR_2(pwm4_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 3), - SENSOR_ATTR_2(pwm4_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 3), - SENSOR_ATTR_2(pwm4_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 3), - SENSOR_ATTR_2(pwm4_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 3), - SENSOR_ATTR_2(pwm4_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 3), - SENSOR_ATTR_2(pwm4_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 3), -} }; - -/* Fan attr specific to the f8000 (4th fan input can only measure speed) */ -static struct sensor_device_attribute_2 f8000_fan_attr[] = { - SENSOR_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 0, 3), -}; - -/* - * PWM attr for the f8000, zones mapped to temp instead of to pwm! - * Also the register block at offset A0 maps to TEMP1 (so our temp2, as the - * F8000 starts counting temps at 0), B0 maps the TEMP2 and C0 maps to TEMP0 - */ -static struct sensor_device_attribute_2 f8000_auto_pwm_attr[3][14] = { { - SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 0), - SENSOR_ATTR_2(temp1_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 2), - SENSOR_ATTR_2(temp1_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 2), - SENSOR_ATTR_2(temp1_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 2), - SENSOR_ATTR_2(temp1_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 2), - SENSOR_ATTR_2(temp1_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 2), - SENSOR_ATTR_2(temp1_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 2), - SENSOR_ATTR_2(temp1_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 2), - SENSOR_ATTR_2(temp1_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 2), - SENSOR_ATTR_2(temp1_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 2), - SENSOR_ATTR_2(temp1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 2), - SENSOR_ATTR_2(temp1_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 2), - SENSOR_ATTR_2(temp1_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 2), - SENSOR_ATTR_2(temp1_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 2), -}, { - SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 1), - SENSOR_ATTR_2(temp2_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 0), - SENSOR_ATTR_2(temp2_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 0), - SENSOR_ATTR_2(temp2_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 0), - SENSOR_ATTR_2(temp2_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 0), - SENSOR_ATTR_2(temp2_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 0), - SENSOR_ATTR_2(temp2_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 0), - SENSOR_ATTR_2(temp2_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 0), - SENSOR_ATTR_2(temp2_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 0), - SENSOR_ATTR_2(temp2_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 0), - SENSOR_ATTR_2(temp2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 0), - SENSOR_ATTR_2(temp2_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 0), - SENSOR_ATTR_2(temp2_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 0), - SENSOR_ATTR_2(temp2_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 0), -}, { - SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_channel, - store_pwm_auto_point_channel, 0, 2), - SENSOR_ATTR_2(temp3_auto_point1_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 0, 1), - SENSOR_ATTR_2(temp3_auto_point2_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 1, 1), - SENSOR_ATTR_2(temp3_auto_point3_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 2, 1), - SENSOR_ATTR_2(temp3_auto_point4_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 3, 1), - SENSOR_ATTR_2(temp3_auto_point5_pwm, S_IRUGO|S_IWUSR, - show_pwm_auto_point_pwm, store_pwm_auto_point_pwm, - 4, 1), - SENSOR_ATTR_2(temp3_auto_point1_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 0, 1), - SENSOR_ATTR_2(temp3_auto_point2_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 1, 1), - SENSOR_ATTR_2(temp3_auto_point3_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 2, 1), - SENSOR_ATTR_2(temp3_auto_point4_temp, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp, store_pwm_auto_point_temp, - 3, 1), - SENSOR_ATTR_2(temp3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR, - show_pwm_auto_point_temp_hyst, - store_pwm_auto_point_temp_hyst, - 0, 1), - SENSOR_ATTR_2(temp3_auto_point2_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 1, 1), - SENSOR_ATTR_2(temp3_auto_point3_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 2, 1), - SENSOR_ATTR_2(temp3_auto_point4_temp_hyst, S_IRUGO, - show_pwm_auto_point_temp_hyst, NULL, 3, 1), -} }; - -/* Super I/O functions */ -static inline int superio_inb(int base, int reg) -{ - outb(reg, base); - return inb(base + 1); -} - -static int superio_inw(int base, int reg) -{ - int val; - val = superio_inb(base, reg) << 8; - val |= superio_inb(base, reg + 1); - return val; -} - -static inline int superio_enter(int base) -{ - /* Don't step on other drivers' I/O space by accident */ - if (!request_muxed_region(base, 2, DRVNAME)) { - pr_err("I/O address 0x%04x already in use\n", base); - return -EBUSY; - } - - /* according to the datasheet the key must be send twice! */ - outb(SIO_UNLOCK_KEY, base); - outb(SIO_UNLOCK_KEY, base); - - return 0; -} - -static inline void superio_select(int base, int ld) -{ - outb(SIO_REG_LDSEL, base); - outb(ld, base + 1); -} - -static inline void superio_exit(int base) -{ - outb(SIO_LOCK_KEY, base); - release_region(base, 2); -} - -static inline int fan_from_reg(u16 reg) -{ - return reg ? (1500000 / reg) : 0; -} - -static inline u16 fan_to_reg(int fan) -{ - return fan ? (1500000 / fan) : 0; -} - -static u8 f71882fg_read8(struct f71882fg_data *data, u8 reg) -{ - u8 val; - - outb(reg, data->addr + ADDR_REG_OFFSET); - val = inb(data->addr + DATA_REG_OFFSET); - - return val; -} - -static u16 f71882fg_read16(struct f71882fg_data *data, u8 reg) -{ - u16 val; - - val = f71882fg_read8(data, reg) << 8; - val |= f71882fg_read8(data, reg + 1); - - return val; -} - -static void f71882fg_write8(struct f71882fg_data *data, u8 reg, u8 val) -{ - outb(reg, data->addr + ADDR_REG_OFFSET); - outb(val, data->addr + DATA_REG_OFFSET); -} - -static void f71882fg_write16(struct f71882fg_data *data, u8 reg, u16 val) -{ - f71882fg_write8(data, reg, val >> 8); - f71882fg_write8(data, reg + 1, val & 0xff); -} - -static u16 f71882fg_read_temp(struct f71882fg_data *data, int nr) -{ - if (data->type == f71858fg) - return f71882fg_read16(data, F71882FG_REG_TEMP(nr)); - else - return f71882fg_read8(data, F71882FG_REG_TEMP(nr)); -} - -static struct f71882fg_data *f71882fg_update_device(struct device *dev) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int nr_fans = f71882fg_nr_fans[data->type]; - int nr_temps = f71882fg_nr_temps[data->type]; - int nr, reg, point; - - mutex_lock(&data->update_lock); - - /* Update once every 60 seconds */ - if (time_after(jiffies, data->last_limits + 60 * HZ) || - !data->valid) { - if (f71882fg_has_in1_alarm[data->type]) { - data->in1_max = - f71882fg_read8(data, F71882FG_REG_IN1_HIGH); - data->in_beep = - f71882fg_read8(data, F71882FG_REG_IN_BEEP); - } - - /* Get High & boundary temps*/ - for (nr = data->temp_start; nr < nr_temps + data->temp_start; - nr++) { - data->temp_ovt[nr] = f71882fg_read8(data, - F71882FG_REG_TEMP_OVT(nr)); - data->temp_high[nr] = f71882fg_read8(data, - F71882FG_REG_TEMP_HIGH(nr)); - } - - if (data->type != f8000) { - data->temp_hyst[0] = f71882fg_read8(data, - F71882FG_REG_TEMP_HYST(0)); - data->temp_hyst[1] = f71882fg_read8(data, - F71882FG_REG_TEMP_HYST(1)); - } - /* All but the f71858fg / f8000 have this register */ - if ((data->type != f71858fg) && (data->type != f8000)) { - reg = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE); - data->temp_type[1] = (reg & 0x02) ? 2 : 4; - data->temp_type[2] = (reg & 0x04) ? 2 : 4; - data->temp_type[3] = (reg & 0x08) ? 2 : 4; - } - - if (f71882fg_fan_has_beep[data->type]) - data->fan_beep = f71882fg_read8(data, - F71882FG_REG_FAN_BEEP); - - if (f71882fg_temp_has_beep[data->type]) - data->temp_beep = f71882fg_read8(data, - F71882FG_REG_TEMP_BEEP); - - data->pwm_enable = f71882fg_read8(data, - F71882FG_REG_PWM_ENABLE); - data->pwm_auto_point_hyst[0] = - f71882fg_read8(data, F71882FG_REG_FAN_HYST(0)); - data->pwm_auto_point_hyst[1] = - f71882fg_read8(data, F71882FG_REG_FAN_HYST(1)); - - for (nr = 0; nr < nr_fans; nr++) { - data->pwm_auto_point_mapping[nr] = - f71882fg_read8(data, - F71882FG_REG_POINT_MAPPING(nr)); - - switch (data->type) { - default: - for (point = 0; point < 5; point++) { - data->pwm_auto_point_pwm[nr][point] = - f71882fg_read8(data, - F71882FG_REG_POINT_PWM - (nr, point)); - } - for (point = 0; point < 4; point++) { - data->pwm_auto_point_temp[nr][point] = - f71882fg_read8(data, - F71882FG_REG_POINT_TEMP - (nr, point)); - } - break; - case f71808e: - case f71869: - data->pwm_auto_point_pwm[nr][0] = - f71882fg_read8(data, - F71882FG_REG_POINT_PWM(nr, 0)); - /* Fall through */ - case f71862fg: - data->pwm_auto_point_pwm[nr][1] = - f71882fg_read8(data, - F71882FG_REG_POINT_PWM - (nr, 1)); - data->pwm_auto_point_pwm[nr][4] = - f71882fg_read8(data, - F71882FG_REG_POINT_PWM - (nr, 4)); - data->pwm_auto_point_temp[nr][0] = - f71882fg_read8(data, - F71882FG_REG_POINT_TEMP - (nr, 0)); - data->pwm_auto_point_temp[nr][3] = - f71882fg_read8(data, - F71882FG_REG_POINT_TEMP - (nr, 3)); - break; - } - } - data->last_limits = jiffies; - } - - /* Update every second */ - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - data->temp_status = f71882fg_read8(data, - F71882FG_REG_TEMP_STATUS); - data->temp_diode_open = f71882fg_read8(data, - F71882FG_REG_TEMP_DIODE_OPEN); - for (nr = data->temp_start; nr < nr_temps + data->temp_start; - nr++) - data->temp[nr] = f71882fg_read_temp(data, nr); - - data->fan_status = f71882fg_read8(data, - F71882FG_REG_FAN_STATUS); - for (nr = 0; nr < nr_fans; nr++) { - data->fan[nr] = f71882fg_read16(data, - F71882FG_REG_FAN(nr)); - data->fan_target[nr] = - f71882fg_read16(data, F71882FG_REG_FAN_TARGET(nr)); - data->fan_full_speed[nr] = - f71882fg_read16(data, - F71882FG_REG_FAN_FULL_SPEED(nr)); - data->pwm[nr] = - f71882fg_read8(data, F71882FG_REG_PWM(nr)); - } - /* Some models have 1 more fan with limited capabilities */ - if (data->type == f71808a) { - data->fan[2] = f71882fg_read16(data, - F71882FG_REG_FAN(2)); - data->pwm[2] = f71882fg_read8(data, - F71882FG_REG_PWM(2)); - } - if (data->type == f8000) - data->fan[3] = f71882fg_read16(data, - F71882FG_REG_FAN(3)); - - if (f71882fg_has_in1_alarm[data->type]) - data->in_status = f71882fg_read8(data, - F71882FG_REG_IN_STATUS); - for (nr = 0; nr < F71882FG_MAX_INS; nr++) - if (f71882fg_has_in[data->type][nr]) - data->in[nr] = f71882fg_read8(data, - F71882FG_REG_IN(nr)); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* Sysfs Interface */ -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - int speed = fan_from_reg(data->fan[nr]); - - if (speed == FAN_MIN_DETECT) - speed = 0; - - return sprintf(buf, "%d\n", speed); -} - -static ssize_t show_fan_full_speed(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - int speed = fan_from_reg(data->fan_full_speed[nr]); - return sprintf(buf, "%d\n", speed); -} - -static ssize_t store_fan_full_speed(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val = SENSORS_LIMIT(val, 23, 1500000); - val = fan_to_reg(val); - - mutex_lock(&data->update_lock); - f71882fg_write16(data, F71882FG_REG_FAN_FULL_SPEED(nr), val); - data->fan_full_speed[nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_fan_beep(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->fan_beep & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_fan_beep(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - unsigned long val; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_beep = f71882fg_read8(data, F71882FG_REG_FAN_BEEP); - if (val) - data->fan_beep |= 1 << nr; - else - data->fan_beep &= ~(1 << nr); - - f71882fg_write8(data, F71882FG_REG_FAN_BEEP, data->fan_beep); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->fan_status & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_in(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - return sprintf(buf, "%d\n", data->in[nr] * 8); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - - return sprintf(buf, "%d\n", data->in1_max * 8); -} - -static ssize_t store_in_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val /= 8; - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - f71882fg_write8(data, F71882FG_REG_IN1_HIGH, val); - data->in1_max = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_in_beep(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->in_beep & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_in_beep(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - unsigned long val; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_beep = f71882fg_read8(data, F71882FG_REG_IN_BEEP); - if (val) - data->in_beep |= 1 << nr; - else - data->in_beep &= ~(1 << nr); - - f71882fg_write8(data, F71882FG_REG_IN_BEEP, data->in_beep); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_in_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->in_status & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - int sign, temp; - - if (data->type == f71858fg) { - /* TEMP_TABLE_SEL 1 or 3 ? */ - if (data->temp_config & 1) { - sign = data->temp[nr] & 0x0001; - temp = (data->temp[nr] >> 5) & 0x7ff; - } else { - sign = data->temp[nr] & 0x8000; - temp = (data->temp[nr] >> 5) & 0x3ff; - } - temp *= 125; - if (sign) - temp -= 128000; - } else - temp = data->temp[nr] * 1000; - - return sprintf(buf, "%d\n", temp); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - return sprintf(buf, "%d\n", data->temp_high[nr] * 1000); -} - -static ssize_t store_temp_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val /= 1000; - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - f71882fg_write8(data, F71882FG_REG_TEMP_HIGH(nr), val); - data->temp_high[nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - int temp_max_hyst; - - mutex_lock(&data->update_lock); - if (nr & 1) - temp_max_hyst = data->temp_hyst[nr / 2] >> 4; - else - temp_max_hyst = data->temp_hyst[nr / 2] & 0x0f; - temp_max_hyst = (data->temp_high[nr] - temp_max_hyst) * 1000; - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", temp_max_hyst); -} - -static ssize_t store_temp_max_hyst(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - ssize_t ret = count; - u8 reg; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val /= 1000; - - mutex_lock(&data->update_lock); - - /* convert abs to relative and check */ - data->temp_high[nr] = f71882fg_read8(data, F71882FG_REG_TEMP_HIGH(nr)); - val = SENSORS_LIMIT(val, data->temp_high[nr] - 15, - data->temp_high[nr]); - val = data->temp_high[nr] - val; - - /* convert value to register contents */ - reg = f71882fg_read8(data, F71882FG_REG_TEMP_HYST(nr / 2)); - if (nr & 1) - reg = (reg & 0x0f) | (val << 4); - else - reg = (reg & 0xf0) | val; - f71882fg_write8(data, F71882FG_REG_TEMP_HYST(nr / 2), reg); - data->temp_hyst[nr / 2] = reg; - - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t show_temp_crit(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - return sprintf(buf, "%d\n", data->temp_ovt[nr] * 1000); -} - -static ssize_t store_temp_crit(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val /= 1000; - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - f71882fg_write8(data, F71882FG_REG_TEMP_OVT(nr), val); - data->temp_ovt[nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp_crit_hyst(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - int temp_crit_hyst; - - mutex_lock(&data->update_lock); - if (nr & 1) - temp_crit_hyst = data->temp_hyst[nr / 2] >> 4; - else - temp_crit_hyst = data->temp_hyst[nr / 2] & 0x0f; - temp_crit_hyst = (data->temp_ovt[nr] - temp_crit_hyst) * 1000; - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", temp_crit_hyst); -} - -static ssize_t show_temp_type(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - return sprintf(buf, "%d\n", data->temp_type[nr]); -} - -static ssize_t show_temp_beep(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->temp_beep & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_temp_beep(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - unsigned long val; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_beep = f71882fg_read8(data, F71882FG_REG_TEMP_BEEP); - if (val) - data->temp_beep |= 1 << nr; - else - data->temp_beep &= ~(1 << nr); - - f71882fg_write8(data, F71882FG_REG_TEMP_BEEP, data->temp_beep); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->temp_status & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - if (data->temp_diode_open & (1 << nr)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_pwm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int val, nr = to_sensor_dev_attr_2(devattr)->index; - mutex_lock(&data->update_lock); - if (data->pwm_enable & (1 << (2 * nr))) - /* PWM mode */ - val = data->pwm[nr]; - else { - /* RPM mode */ - val = 255 * fan_from_reg(data->fan_target[nr]) - / fan_from_reg(data->fan_full_speed[nr]); - } - mutex_unlock(&data->update_lock); - return sprintf(buf, "%d\n", val); -} - -static ssize_t store_pwm(struct device *dev, - struct device_attribute *devattr, const char *buf, - size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - if ((data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 3) != 2) || - (data->type != f8000 && !((data->pwm_enable >> 2 * nr) & 2))) { - count = -EROFS; - goto leave; - } - if (data->pwm_enable & (1 << (2 * nr))) { - /* PWM mode */ - f71882fg_write8(data, F71882FG_REG_PWM(nr), val); - data->pwm[nr] = val; - } else { - /* RPM mode */ - int target, full_speed; - full_speed = f71882fg_read16(data, - F71882FG_REG_FAN_FULL_SPEED(nr)); - target = fan_to_reg(val * fan_from_reg(full_speed) / 255); - f71882fg_write16(data, F71882FG_REG_FAN_TARGET(nr), target); - data->fan_target[nr] = target; - data->fan_full_speed[nr] = full_speed; - } -leave: - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_simple_pwm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct f71882fg_data *data = f71882fg_update_device(dev); - int val, nr = to_sensor_dev_attr_2(devattr)->index; - - val = data->pwm[nr]; - return sprintf(buf, "%d\n", val); -} - -static ssize_t store_simple_pwm(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - f71882fg_write8(data, F71882FG_REG_PWM(nr), val); - data->pwm[nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int result = 0; - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - switch ((data->pwm_enable >> 2 * nr) & 3) { - case 0: - case 1: - result = 2; /* Normal auto mode */ - break; - case 2: - result = 1; /* Manual mode */ - break; - case 3: - if (data->type == f8000) - result = 3; /* Thermostat mode */ - else - result = 1; /* Manual mode */ - break; - } - - return sprintf(buf, "%d\n", result); -} - -static ssize_t store_pwm_enable(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - /* Special case for F8000 pwm channel 3 which only does auto mode */ - if (data->type == f8000 && nr == 2 && val != 2) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - /* Special case for F8000 auto PWM mode / Thermostat mode */ - if (data->type == f8000 && ((data->pwm_enable >> 2 * nr) & 1)) { - switch (val) { - case 2: - data->pwm_enable &= ~(2 << (2 * nr)); - break; /* Normal auto mode */ - case 3: - data->pwm_enable |= 2 << (2 * nr); - break; /* Thermostat mode */ - default: - count = -EINVAL; - goto leave; - } - } else { - switch (val) { - case 1: - /* The f71858fg does not support manual RPM mode */ - if (data->type == f71858fg && - ((data->pwm_enable >> (2 * nr)) & 1)) { - count = -EINVAL; - goto leave; - } - data->pwm_enable |= 2 << (2 * nr); - break; /* Manual */ - case 2: - data->pwm_enable &= ~(2 << (2 * nr)); - break; /* Normal auto mode */ - default: - count = -EINVAL; - goto leave; - } - } - f71882fg_write8(data, F71882FG_REG_PWM_ENABLE, data->pwm_enable); -leave: - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_auto_point_pwm(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - int result; - struct f71882fg_data *data = f71882fg_update_device(dev); - int pwm = to_sensor_dev_attr_2(devattr)->index; - int point = to_sensor_dev_attr_2(devattr)->nr; - - mutex_lock(&data->update_lock); - if (data->pwm_enable & (1 << (2 * pwm))) { - /* PWM mode */ - result = data->pwm_auto_point_pwm[pwm][point]; - } else { - /* RPM mode */ - result = 32 * 255 / (32 + data->pwm_auto_point_pwm[pwm][point]); - } - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", result); -} - -static ssize_t store_pwm_auto_point_pwm(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, pwm = to_sensor_dev_attr_2(devattr)->index; - int point = to_sensor_dev_attr_2(devattr)->nr; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - data->pwm_enable = f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - if (data->pwm_enable & (1 << (2 * pwm))) { - /* PWM mode */ - } else { - /* RPM mode */ - if (val < 29) /* Prevent negative numbers */ - val = 255; - else - val = (255 - val) * 32 / val; - } - f71882fg_write8(data, F71882FG_REG_POINT_PWM(pwm, point), val); - data->pwm_auto_point_pwm[pwm][point] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_auto_point_temp_hyst(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - int result = 0; - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - int point = to_sensor_dev_attr_2(devattr)->nr; - - mutex_lock(&data->update_lock); - if (nr & 1) - result = data->pwm_auto_point_hyst[nr / 2] >> 4; - else - result = data->pwm_auto_point_hyst[nr / 2] & 0x0f; - result = 1000 * (data->pwm_auto_point_temp[nr][point] - result); - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", result); -} - -static ssize_t store_pwm_auto_point_temp_hyst(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - int point = to_sensor_dev_attr_2(devattr)->nr; - u8 reg; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val /= 1000; - - mutex_lock(&data->update_lock); - data->pwm_auto_point_temp[nr][point] = - f71882fg_read8(data, F71882FG_REG_POINT_TEMP(nr, point)); - val = SENSORS_LIMIT(val, data->pwm_auto_point_temp[nr][point] - 15, - data->pwm_auto_point_temp[nr][point]); - val = data->pwm_auto_point_temp[nr][point] - val; - - reg = f71882fg_read8(data, F71882FG_REG_FAN_HYST(nr / 2)); - if (nr & 1) - reg = (reg & 0x0f) | (val << 4); - else - reg = (reg & 0xf0) | val; - - f71882fg_write8(data, F71882FG_REG_FAN_HYST(nr / 2), reg); - data->pwm_auto_point_hyst[nr / 2] = reg; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_interpolate(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int result; - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - result = (data->pwm_auto_point_mapping[nr] >> 4) & 1; - - return sprintf(buf, "%d\n", result); -} - -static ssize_t store_pwm_interpolate(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - unsigned long val; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm_auto_point_mapping[nr] = - f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); - if (val) - val = data->pwm_auto_point_mapping[nr] | (1 << 4); - else - val = data->pwm_auto_point_mapping[nr] & (~(1 << 4)); - f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); - data->pwm_auto_point_mapping[nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_auto_point_channel(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - int result; - struct f71882fg_data *data = f71882fg_update_device(dev); - int nr = to_sensor_dev_attr_2(devattr)->index; - - result = 1 << ((data->pwm_auto_point_mapping[nr] & 3) - - data->temp_start); - - return sprintf(buf, "%d\n", result); -} - -static ssize_t store_pwm_auto_point_channel(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, nr = to_sensor_dev_attr_2(devattr)->index; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - switch (val) { - case 1: - val = 0; - break; - case 2: - val = 1; - break; - case 4: - val = 2; - break; - default: - return -EINVAL; - } - val += data->temp_start; - mutex_lock(&data->update_lock); - data->pwm_auto_point_mapping[nr] = - f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(nr)); - val = (data->pwm_auto_point_mapping[nr] & 0xfc) | val; - f71882fg_write8(data, F71882FG_REG_POINT_MAPPING(nr), val); - data->pwm_auto_point_mapping[nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_pwm_auto_point_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - int result; - struct f71882fg_data *data = f71882fg_update_device(dev); - int pwm = to_sensor_dev_attr_2(devattr)->index; - int point = to_sensor_dev_attr_2(devattr)->nr; - - result = data->pwm_auto_point_temp[pwm][point]; - return sprintf(buf, "%d\n", 1000 * result); -} - -static ssize_t store_pwm_auto_point_temp(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - int err, pwm = to_sensor_dev_attr_2(devattr)->index; - int point = to_sensor_dev_attr_2(devattr)->nr; - long val; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - val /= 1000; - - if (data->auto_point_temp_signed) - val = SENSORS_LIMIT(val, -128, 127); - else - val = SENSORS_LIMIT(val, 0, 127); - - mutex_lock(&data->update_lock); - f71882fg_write8(data, F71882FG_REG_POINT_TEMP(pwm, point), val); - data->pwm_auto_point_temp[pwm][point] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct f71882fg_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", f71882fg_names[data->type]); -} - -static int __devinit f71882fg_create_sysfs_files(struct platform_device *pdev, - struct sensor_device_attribute_2 *attr, int count) -{ - int err, i; - - for (i = 0; i < count; i++) { - err = device_create_file(&pdev->dev, &attr[i].dev_attr); - if (err) - return err; - } - return 0; -} - -static void f71882fg_remove_sysfs_files(struct platform_device *pdev, - struct sensor_device_attribute_2 *attr, int count) -{ - int i; - - for (i = 0; i < count; i++) - device_remove_file(&pdev->dev, &attr[i].dev_attr); -} - -static int __devinit f71882fg_create_fan_sysfs_files( - struct platform_device *pdev, int idx) -{ - struct f71882fg_data *data = platform_get_drvdata(pdev); - int err; - - /* Sanity check the pwm setting */ - err = 0; - switch (data->type) { - case f71858fg: - if (((data->pwm_enable >> (idx * 2)) & 3) == 3) - err = 1; - break; - case f71862fg: - if (((data->pwm_enable >> (idx * 2)) & 1) != 1) - err = 1; - break; - case f8000: - if (idx == 2) - err = data->pwm_enable & 0x20; - break; - default: - break; - } - if (err) { - dev_err(&pdev->dev, - "Invalid (reserved) pwm settings: 0x%02x, " - "skipping fan %d\n", - (data->pwm_enable >> (idx * 2)) & 3, idx + 1); - return 0; /* This is a non fatal condition */ - } - - err = f71882fg_create_sysfs_files(pdev, &fxxxx_fan_attr[idx][0], - ARRAY_SIZE(fxxxx_fan_attr[0])); - if (err) - return err; - - if (f71882fg_fan_has_beep[data->type]) { - err = f71882fg_create_sysfs_files(pdev, - &fxxxx_fan_beep_attr[idx], - 1); - if (err) - return err; - } - - dev_info(&pdev->dev, "Fan: %d is in %s mode\n", idx + 1, - (data->pwm_enable & (1 << (2 * idx))) ? "duty-cycle" : "RPM"); - - /* Check for unsupported auto pwm settings */ - switch (data->type) { - case f71808e: - case f71808a: - case f71869: - case f71869a: - case f71889fg: - case f71889ed: - case f71889a: - data->pwm_auto_point_mapping[idx] = - f71882fg_read8(data, F71882FG_REG_POINT_MAPPING(idx)); - if ((data->pwm_auto_point_mapping[idx] & 0x80) || - (data->pwm_auto_point_mapping[idx] & 3) == 0) { - dev_warn(&pdev->dev, - "Auto pwm controlled by raw digital " - "data, disabling pwm auto_point " - "sysfs attributes for fan %d\n", idx + 1); - return 0; /* This is a non fatal condition */ - } - break; - default: - break; - } - - switch (data->type) { - case f71862fg: - err = f71882fg_create_sysfs_files(pdev, - &f71862fg_auto_pwm_attr[idx][0], - ARRAY_SIZE(f71862fg_auto_pwm_attr[0])); - break; - case f71808e: - case f71869: - err = f71882fg_create_sysfs_files(pdev, - &f71869_auto_pwm_attr[idx][0], - ARRAY_SIZE(f71869_auto_pwm_attr[0])); - break; - case f8000: - err = f71882fg_create_sysfs_files(pdev, - &f8000_auto_pwm_attr[idx][0], - ARRAY_SIZE(f8000_auto_pwm_attr[0])); - break; - default: - err = f71882fg_create_sysfs_files(pdev, - &fxxxx_auto_pwm_attr[idx][0], - ARRAY_SIZE(fxxxx_auto_pwm_attr[0])); - } - - return err; -} - -static int __devinit f71882fg_probe(struct platform_device *pdev) -{ - struct f71882fg_data *data; - struct f71882fg_sio_data *sio_data = pdev->dev.platform_data; - int nr_fans = f71882fg_nr_fans[sio_data->type]; - int nr_temps = f71882fg_nr_temps[sio_data->type]; - int err, i; - u8 start_reg, reg; - - data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; - data->type = sio_data->type; - data->temp_start = - (data->type == f71858fg || data->type == f8000) ? 0 : 1; - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - start_reg = f71882fg_read8(data, F71882FG_REG_START); - if (start_reg & 0x04) { - dev_warn(&pdev->dev, "Hardware monitor is powered down\n"); - err = -ENODEV; - goto exit_free; - } - if (!(start_reg & 0x03)) { - dev_warn(&pdev->dev, "Hardware monitoring not activated\n"); - err = -ENODEV; - goto exit_free; - } - - /* Register sysfs interface files */ - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_unregister_sysfs; - - if (start_reg & 0x01) { - switch (data->type) { - case f71858fg: - data->temp_config = - f71882fg_read8(data, F71882FG_REG_TEMP_CONFIG); - if (data->temp_config & 0x10) - /* - * The f71858fg temperature alarms behave as - * the f8000 alarms in this mode - */ - err = f71882fg_create_sysfs_files(pdev, - f8000_temp_attr, - ARRAY_SIZE(f8000_temp_attr)); - else - err = f71882fg_create_sysfs_files(pdev, - f71858fg_temp_attr, - ARRAY_SIZE(f71858fg_temp_attr)); - break; - case f8000: - err = f71882fg_create_sysfs_files(pdev, - f8000_temp_attr, - ARRAY_SIZE(f8000_temp_attr)); - break; - default: - err = f71882fg_create_sysfs_files(pdev, - &fxxxx_temp_attr[0][0], - ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps); - } - if (err) - goto exit_unregister_sysfs; - - if (f71882fg_temp_has_beep[data->type]) { - err = f71882fg_create_sysfs_files(pdev, - &fxxxx_temp_beep_attr[0][0], - ARRAY_SIZE(fxxxx_temp_beep_attr[0]) - * nr_temps); - if (err) - goto exit_unregister_sysfs; - } - - for (i = 0; i < F71882FG_MAX_INS; i++) { - if (f71882fg_has_in[data->type][i]) { - err = device_create_file(&pdev->dev, - &fxxxx_in_attr[i].dev_attr); - if (err) - goto exit_unregister_sysfs; - } - } - if (f71882fg_has_in1_alarm[data->type]) { - err = f71882fg_create_sysfs_files(pdev, - fxxxx_in1_alarm_attr, - ARRAY_SIZE(fxxxx_in1_alarm_attr)); - if (err) - goto exit_unregister_sysfs; - } - } - - if (start_reg & 0x02) { - switch (data->type) { - case f71808e: - case f71808a: - case f71869: - case f71869a: - /* These always have signed auto point temps */ - data->auto_point_temp_signed = 1; - /* Fall through to select correct fan/pwm reg bank! */ - case f71889fg: - case f71889ed: - case f71889a: - reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T); - if (reg & F71882FG_FAN_NEG_TEMP_EN) - data->auto_point_temp_signed = 1; - /* Ensure banked pwm registers point to right bank */ - reg &= ~F71882FG_FAN_PROG_SEL; - f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg); - break; - default: - break; - } - - data->pwm_enable = - f71882fg_read8(data, F71882FG_REG_PWM_ENABLE); - - for (i = 0; i < nr_fans; i++) { - err = f71882fg_create_fan_sysfs_files(pdev, i); - if (err) - goto exit_unregister_sysfs; - } - - /* Some types have 1 extra fan with limited functionality */ - switch (data->type) { - case f71808a: - err = f71882fg_create_sysfs_files(pdev, - f71808a_fan3_attr, - ARRAY_SIZE(f71808a_fan3_attr)); - break; - case f8000: - err = f71882fg_create_sysfs_files(pdev, - f8000_fan_attr, - ARRAY_SIZE(f8000_fan_attr)); - break; - default: - break; - } - if (err) - goto exit_unregister_sysfs; - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - data->hwmon_dev = NULL; - goto exit_unregister_sysfs; - } - - return 0; - -exit_unregister_sysfs: - f71882fg_remove(pdev); /* Will unregister the sysfs files for us */ - return err; /* f71882fg_remove() also frees our data */ -exit_free: - kfree(data); - return err; -} - -static int f71882fg_remove(struct platform_device *pdev) -{ - struct f71882fg_data *data = platform_get_drvdata(pdev); - int nr_fans = f71882fg_nr_fans[data->type]; - int nr_temps = f71882fg_nr_temps[data->type]; - int i; - u8 start_reg = f71882fg_read8(data, F71882FG_REG_START); - - if (data->hwmon_dev) - hwmon_device_unregister(data->hwmon_dev); - - device_remove_file(&pdev->dev, &dev_attr_name); - - if (start_reg & 0x01) { - switch (data->type) { - case f71858fg: - if (data->temp_config & 0x10) - f71882fg_remove_sysfs_files(pdev, - f8000_temp_attr, - ARRAY_SIZE(f8000_temp_attr)); - else - f71882fg_remove_sysfs_files(pdev, - f71858fg_temp_attr, - ARRAY_SIZE(f71858fg_temp_attr)); - break; - case f8000: - f71882fg_remove_sysfs_files(pdev, - f8000_temp_attr, - ARRAY_SIZE(f8000_temp_attr)); - break; - default: - f71882fg_remove_sysfs_files(pdev, - &fxxxx_temp_attr[0][0], - ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps); - } - if (f71882fg_temp_has_beep[data->type]) { - f71882fg_remove_sysfs_files(pdev, - &fxxxx_temp_beep_attr[0][0], - ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps); - } - - for (i = 0; i < F71882FG_MAX_INS; i++) { - if (f71882fg_has_in[data->type][i]) { - device_remove_file(&pdev->dev, - &fxxxx_in_attr[i].dev_attr); - } - } - if (f71882fg_has_in1_alarm[data->type]) { - f71882fg_remove_sysfs_files(pdev, - fxxxx_in1_alarm_attr, - ARRAY_SIZE(fxxxx_in1_alarm_attr)); - } - } - - if (start_reg & 0x02) { - f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0], - ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans); - - if (f71882fg_fan_has_beep[data->type]) { - f71882fg_remove_sysfs_files(pdev, - fxxxx_fan_beep_attr, nr_fans); - } - - switch (data->type) { - case f71808a: - f71882fg_remove_sysfs_files(pdev, - &fxxxx_auto_pwm_attr[0][0], - ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); - f71882fg_remove_sysfs_files(pdev, - f71808a_fan3_attr, - ARRAY_SIZE(f71808a_fan3_attr)); - break; - case f71862fg: - f71882fg_remove_sysfs_files(pdev, - &f71862fg_auto_pwm_attr[0][0], - ARRAY_SIZE(f71862fg_auto_pwm_attr[0]) * - nr_fans); - break; - case f71808e: - case f71869: - f71882fg_remove_sysfs_files(pdev, - &f71869_auto_pwm_attr[0][0], - ARRAY_SIZE(f71869_auto_pwm_attr[0]) * nr_fans); - break; - case f8000: - f71882fg_remove_sysfs_files(pdev, - f8000_fan_attr, - ARRAY_SIZE(f8000_fan_attr)); - f71882fg_remove_sysfs_files(pdev, - &f8000_auto_pwm_attr[0][0], - ARRAY_SIZE(f8000_auto_pwm_attr[0]) * nr_fans); - break; - default: - f71882fg_remove_sysfs_files(pdev, - &fxxxx_auto_pwm_attr[0][0], - ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); - } - } - - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static int __init f71882fg_find(int sioaddr, unsigned short *address, - struct f71882fg_sio_data *sio_data) -{ - u16 devid; - int err = superio_enter(sioaddr); - if (err) - return err; - - devid = superio_inw(sioaddr, SIO_REG_MANID); - if (devid != SIO_FINTEK_ID) { - pr_debug("Not a Fintek device\n"); - err = -ENODEV; - goto exit; - } - - devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID); - switch (devid) { - case SIO_F71808E_ID: - sio_data->type = f71808e; - break; - case SIO_F71808A_ID: - sio_data->type = f71808a; - break; - case SIO_F71858_ID: - sio_data->type = f71858fg; - break; - case SIO_F71862_ID: - sio_data->type = f71862fg; - break; - case SIO_F71869_ID: - sio_data->type = f71869; - break; - case SIO_F71869A_ID: - sio_data->type = f71869a; - break; - case SIO_F71882_ID: - sio_data->type = f71882fg; - break; - case SIO_F71889_ID: - sio_data->type = f71889fg; - break; - case SIO_F71889E_ID: - sio_data->type = f71889ed; - break; - case SIO_F71889A_ID: - sio_data->type = f71889a; - break; - case SIO_F8000_ID: - sio_data->type = f8000; - break; - case SIO_F81865_ID: - sio_data->type = f81865f; - break; - default: - pr_info("Unsupported Fintek device: %04x\n", - (unsigned int)devid); - err = -ENODEV; - goto exit; - } - - if (sio_data->type == f71858fg) - superio_select(sioaddr, SIO_F71858FG_LD_HWM); - else - superio_select(sioaddr, SIO_F71882FG_LD_HWM); - - if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - pr_warn("Device not activated\n"); - err = -ENODEV; - goto exit; - } - - *address = superio_inw(sioaddr, SIO_REG_ADDR); - if (*address == 0) { - pr_warn("Base address not set\n"); - err = -ENODEV; - goto exit; - } - *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ - - err = 0; - pr_info("Found %s chip at %#x, revision %d\n", - f71882fg_names[sio_data->type], (unsigned int)*address, - (int)superio_inb(sioaddr, SIO_REG_DEVREV)); -exit: - superio_exit(sioaddr); - return err; -} - -static int __init f71882fg_device_add(unsigned short address, - const struct f71882fg_sio_data *sio_data) -{ - struct resource res = { - .start = address, - .end = address + REGION_LENGTH - 1, - .flags = IORESOURCE_IO, - }; - int err; - - f71882fg_pdev = platform_device_alloc(DRVNAME, address); - if (!f71882fg_pdev) - return -ENOMEM; - - res.name = f71882fg_pdev->name; - err = acpi_check_resource_conflict(&res); - if (err) - goto exit_device_put; - - err = platform_device_add_resources(f71882fg_pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed\n"); - goto exit_device_put; - } - - err = platform_device_add_data(f71882fg_pdev, sio_data, - sizeof(struct f71882fg_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - err = platform_device_add(f71882fg_pdev); - if (err) { - pr_err("Device addition failed\n"); - goto exit_device_put; - } - - return 0; - -exit_device_put: - platform_device_put(f71882fg_pdev); - - return err; -} - -static int __init f71882fg_init(void) -{ - int err = -ENODEV; - unsigned short address; - struct f71882fg_sio_data sio_data; - - memset(&sio_data, 0, sizeof(sio_data)); - - if (f71882fg_find(0x2e, &address, &sio_data) && - f71882fg_find(0x4e, &address, &sio_data)) - goto exit; - - err = platform_driver_register(&f71882fg_driver); - if (err) - goto exit; - - err = f71882fg_device_add(address, &sio_data); - if (err) - goto exit_driver; - - return 0; - -exit_driver: - platform_driver_unregister(&f71882fg_driver); -exit: - return err; -} - -static void __exit f71882fg_exit(void) -{ - platform_device_unregister(f71882fg_pdev); - platform_driver_unregister(&f71882fg_driver); -} - -MODULE_DESCRIPTION("F71882FG Hardware Monitoring Driver"); -MODULE_AUTHOR("Hans Edgington, Hans de Goede "); -MODULE_LICENSE("GPL"); - -module_init(f71882fg_init); -module_exit(f71882fg_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/f75375s.c b/ANDROID_3.4.5/drivers/hwmon/f75375s.c deleted file mode 100644 index ece4159b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/f75375s.c +++ /dev/null @@ -1,926 +0,0 @@ -/* - * f75375s.c - driver for the Fintek F75375/SP, F75373 and - * F75387SG/RG hardware monitoring features - * Copyright (C) 2006-2007 Riku Voipio - * - * Datasheets available at: - * - * f75375: - * http://www.fintek.com.tw/files/productfiles/F75375_V026P.pdf - * - * f75373: - * http://www.fintek.com.tw/files/productfiles/F75373_V025P.pdf - * - * f75387: - * http://www.fintek.com.tw/files/productfiles/F75387_V027P.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2d, 0x2e, I2C_CLIENT_END }; - -enum chips { f75373, f75375, f75387 }; - -/* Fintek F75375 registers */ -#define F75375_REG_CONFIG0 0x0 -#define F75375_REG_CONFIG1 0x1 -#define F75375_REG_CONFIG2 0x2 -#define F75375_REG_CONFIG3 0x3 -#define F75375_REG_ADDR 0x4 -#define F75375_REG_INTR 0x31 -#define F75375_CHIP_ID 0x5A -#define F75375_REG_VERSION 0x5C -#define F75375_REG_VENDOR 0x5D -#define F75375_REG_FAN_TIMER 0x60 - -#define F75375_REG_VOLT(nr) (0x10 + (nr)) -#define F75375_REG_VOLT_HIGH(nr) (0x20 + (nr) * 2) -#define F75375_REG_VOLT_LOW(nr) (0x21 + (nr) * 2) - -#define F75375_REG_TEMP(nr) (0x14 + (nr)) -#define F75387_REG_TEMP11_LSB(nr) (0x1a + (nr)) -#define F75375_REG_TEMP_HIGH(nr) (0x28 + (nr) * 2) -#define F75375_REG_TEMP_HYST(nr) (0x29 + (nr) * 2) - -#define F75375_REG_FAN(nr) (0x16 + (nr) * 2) -#define F75375_REG_FAN_MIN(nr) (0x2C + (nr) * 2) -#define F75375_REG_FAN_FULL(nr) (0x70 + (nr) * 0x10) -#define F75375_REG_FAN_PWM_DUTY(nr) (0x76 + (nr) * 0x10) -#define F75375_REG_FAN_PWM_CLOCK(nr) (0x7D + (nr) * 0x10) - -#define F75375_REG_FAN_EXP(nr) (0x74 + (nr) * 0x10) -#define F75375_REG_FAN_B_TEMP(nr, step) ((0xA0 + (nr) * 0x10) + (step)) -#define F75375_REG_FAN_B_SPEED(nr, step) \ - ((0xA5 + (nr) * 0x10) + (step) * 2) - -#define F75375_REG_PWM1_RAISE_DUTY 0x69 -#define F75375_REG_PWM2_RAISE_DUTY 0x6A -#define F75375_REG_PWM1_DROP_DUTY 0x6B -#define F75375_REG_PWM2_DROP_DUTY 0x6C - -#define F75375_FAN_CTRL_LINEAR(nr) (4 + nr) -#define F75387_FAN_CTRL_LINEAR(nr) (1 + ((nr) * 4)) -#define FAN_CTRL_MODE(nr) (4 + ((nr) * 2)) -#define F75387_FAN_DUTY_MODE(nr) (2 + ((nr) * 4)) -#define F75387_FAN_MANU_MODE(nr) ((nr) * 4) - -/* - * Data structures and manipulation thereof - */ - -struct f75375_data { - unsigned short addr; - struct device *hwmon_dev; - - const char *name; - int kind; - struct mutex update_lock; /* protect register access */ - char valid; - unsigned long last_updated; /* In jiffies */ - unsigned long last_limits; /* In jiffies */ - - /* Register values */ - u8 in[4]; - u8 in_max[4]; - u8 in_min[4]; - u16 fan[2]; - u16 fan_min[2]; - u16 fan_max[2]; - u16 fan_target[2]; - u8 fan_timer; - u8 pwm[2]; - u8 pwm_mode[2]; - u8 pwm_enable[2]; - /* - * f75387: For remote temperature reading, it uses signed 11-bit - * values with LSB = 0.125 degree Celsius, left-justified in 16-bit - * registers. For original 8-bit temp readings, the LSB just is 0. - */ - s16 temp11[2]; - s8 temp_high[2]; - s8 temp_max_hyst[2]; -}; - -static int f75375_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int f75375_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int f75375_remove(struct i2c_client *client); - -static const struct i2c_device_id f75375_id[] = { - { "f75373", f75373 }, - { "f75375", f75375 }, - { "f75387", f75387 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, f75375_id); - -static struct i2c_driver f75375_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "f75375", - }, - .probe = f75375_probe, - .remove = f75375_remove, - .id_table = f75375_id, - .detect = f75375_detect, - .address_list = normal_i2c, -}; - -static inline int f75375_read8(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -/* in most cases, should be called while holding update_lock */ -static inline u16 f75375_read16(struct i2c_client *client, u8 reg) -{ - return (i2c_smbus_read_byte_data(client, reg) << 8) - | i2c_smbus_read_byte_data(client, reg + 1); -} - -static inline void f75375_write8(struct i2c_client *client, u8 reg, - u8 value) -{ - i2c_smbus_write_byte_data(client, reg, value); -} - -static inline void f75375_write16(struct i2c_client *client, u8 reg, - u16 value) -{ - int err = i2c_smbus_write_byte_data(client, reg, (value >> 8)); - if (err) - return; - i2c_smbus_write_byte_data(client, reg + 1, (value & 0xFF)); -} - -static void f75375_write_pwm(struct i2c_client *client, int nr) -{ - struct f75375_data *data = i2c_get_clientdata(client); - if (data->kind == f75387) - f75375_write16(client, F75375_REG_FAN_EXP(nr), data->pwm[nr]); - else - f75375_write8(client, F75375_REG_FAN_PWM_DUTY(nr), - data->pwm[nr]); -} - -static struct f75375_data *f75375_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - int nr; - - mutex_lock(&data->update_lock); - - /* Limit registers cache is refreshed after 60 seconds */ - if (time_after(jiffies, data->last_limits + 60 * HZ) - || !data->valid) { - for (nr = 0; nr < 2; nr++) { - data->temp_high[nr] = - f75375_read8(client, F75375_REG_TEMP_HIGH(nr)); - data->temp_max_hyst[nr] = - f75375_read8(client, F75375_REG_TEMP_HYST(nr)); - data->fan_max[nr] = - f75375_read16(client, F75375_REG_FAN_FULL(nr)); - data->fan_min[nr] = - f75375_read16(client, F75375_REG_FAN_MIN(nr)); - data->fan_target[nr] = - f75375_read16(client, F75375_REG_FAN_EXP(nr)); - } - for (nr = 0; nr < 4; nr++) { - data->in_max[nr] = - f75375_read8(client, F75375_REG_VOLT_HIGH(nr)); - data->in_min[nr] = - f75375_read8(client, F75375_REG_VOLT_LOW(nr)); - } - data->fan_timer = f75375_read8(client, F75375_REG_FAN_TIMER); - data->last_limits = jiffies; - } - - /* Measurement registers cache is refreshed after 2 second */ - if (time_after(jiffies, data->last_updated + 2 * HZ) - || !data->valid) { - for (nr = 0; nr < 2; nr++) { - data->pwm[nr] = f75375_read8(client, - F75375_REG_FAN_PWM_DUTY(nr)); - /* assign MSB, therefore shift it by 8 bits */ - data->temp11[nr] = - f75375_read8(client, F75375_REG_TEMP(nr)) << 8; - if (data->kind == f75387) - /* merge F75387's temperature LSB (11-bit) */ - data->temp11[nr] |= - f75375_read8(client, - F75387_REG_TEMP11_LSB(nr)); - data->fan[nr] = - f75375_read16(client, F75375_REG_FAN(nr)); - } - for (nr = 0; nr < 4; nr++) - data->in[nr] = - f75375_read8(client, F75375_REG_VOLT(nr)); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - return data; -} - -static inline u16 rpm_from_reg(u16 reg) -{ - if (reg == 0 || reg == 0xffff) - return 0; - return 1500000 / reg; -} - -static inline u16 rpm_to_reg(int rpm) -{ - if (rpm < 367 || rpm > 0xffff) - return 0xffff; - return 1500000 / rpm; -} - -static bool duty_mode_enabled(u8 pwm_enable) -{ - switch (pwm_enable) { - case 0: /* Manual, duty mode (full speed) */ - case 1: /* Manual, duty mode */ - case 4: /* Auto, duty mode */ - return true; - case 2: /* Auto, speed mode */ - case 3: /* Manual, speed mode */ - return false; - default: - BUG(); - return true; - } -} - -static bool auto_mode_enabled(u8 pwm_enable) -{ - switch (pwm_enable) { - case 0: /* Manual, duty mode (full speed) */ - case 1: /* Manual, duty mode */ - case 3: /* Manual, speed mode */ - return false; - case 2: /* Auto, speed mode */ - case 4: /* Auto, duty mode */ - return true; - default: - BUG(); - return false; - } -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = rpm_to_reg(val); - f75375_write16(client, F75375_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_fan_target(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - if (auto_mode_enabled(data->pwm_enable[nr])) - return -EINVAL; - if (data->kind == f75387 && duty_mode_enabled(data->pwm_enable[nr])) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->fan_target[nr] = rpm_to_reg(val); - f75375_write16(client, F75375_REG_FAN_EXP(nr), data->fan_target[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - if (auto_mode_enabled(data->pwm_enable[nr]) || - !duty_mode_enabled(data->pwm_enable[nr])) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); - f75375_write_pwm(client, nr); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_enable(struct device *dev, struct device_attribute - *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_enable[nr]); -} - -static int set_pwm_enable_direct(struct i2c_client *client, int nr, int val) -{ - struct f75375_data *data = i2c_get_clientdata(client); - u8 fanmode; - - if (val < 0 || val > 4) - return -EINVAL; - - fanmode = f75375_read8(client, F75375_REG_FAN_TIMER); - if (data->kind == f75387) { - /* For now, deny dangerous toggling of duty mode */ - if (duty_mode_enabled(data->pwm_enable[nr]) != - duty_mode_enabled(val)) - return -EOPNOTSUPP; - /* clear each fanX_mode bit before setting them properly */ - fanmode &= ~(1 << F75387_FAN_DUTY_MODE(nr)); - fanmode &= ~(1 << F75387_FAN_MANU_MODE(nr)); - switch (val) { - case 0: /* full speed */ - fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); - fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); - data->pwm[nr] = 255; - break; - case 1: /* PWM */ - fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); - fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); - break; - case 2: /* Automatic, speed mode */ - break; - case 3: /* fan speed */ - fanmode |= (1 << F75387_FAN_MANU_MODE(nr)); - break; - case 4: /* Automatic, pwm */ - fanmode |= (1 << F75387_FAN_DUTY_MODE(nr)); - break; - } - } else { - /* clear each fanX_mode bit before setting them properly */ - fanmode &= ~(3 << FAN_CTRL_MODE(nr)); - switch (val) { - case 0: /* full speed */ - fanmode |= (3 << FAN_CTRL_MODE(nr)); - data->pwm[nr] = 255; - break; - case 1: /* PWM */ - fanmode |= (3 << FAN_CTRL_MODE(nr)); - break; - case 2: /* AUTOMATIC*/ - fanmode |= (1 << FAN_CTRL_MODE(nr)); - break; - case 3: /* fan speed */ - break; - case 4: /* Automatic pwm */ - return -EINVAL; - } - } - - f75375_write8(client, F75375_REG_FAN_TIMER, fanmode); - data->pwm_enable[nr] = val; - if (val == 0) - f75375_write_pwm(client, nr); - return 0; -} - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - mutex_lock(&data->update_lock); - err = set_pwm_enable_direct(client, nr, val); - mutex_unlock(&data->update_lock); - return err ? err : count; -} - -static ssize_t set_pwm_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - u8 conf; - char reg, ctrl; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - if (!(val == 0 || val == 1)) - return -EINVAL; - - /* F75373 does not support DC (linear voltage) fan control mode */ - if (data->kind == f75373 && val == 0) - return -EINVAL; - - /* take care for different registers */ - if (data->kind == f75387) { - reg = F75375_REG_FAN_TIMER; - ctrl = F75387_FAN_CTRL_LINEAR(nr); - } else { - reg = F75375_REG_CONFIG1; - ctrl = F75375_FAN_CTRL_LINEAR(nr); - } - - mutex_lock(&data->update_lock); - conf = f75375_read8(client, reg); - conf &= ~(1 << ctrl); - - if (val == 0) - conf |= (1 << ctrl); - - f75375_write8(client, reg, conf); - data->pwm_mode[nr] = val; - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute - *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", data->pwm[nr]); -} - -static ssize_t show_pwm_mode(struct device *dev, struct device_attribute - *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_mode[nr]); -} - -#define VOLT_FROM_REG(val) ((val) * 8) -#define VOLT_TO_REG(val) ((val) / 8) - -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", VOLT_FROM_REG(data->in[nr])); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", VOLT_FROM_REG(data->in_max[nr])); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", VOLT_FROM_REG(data->in_min[nr])); -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - val = SENSORS_LIMIT(VOLT_TO_REG(val), 0, 0xff); - mutex_lock(&data->update_lock); - data->in_max[nr] = val; - f75375_write8(client, F75375_REG_VOLT_HIGH(nr), data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - val = SENSORS_LIMIT(VOLT_TO_REG(val), 0, 0xff); - mutex_lock(&data->update_lock); - data->in_min[nr] = val; - f75375_write8(client, F75375_REG_VOLT_LOW(nr), data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -#define TEMP_FROM_REG(val) ((val) * 1000) -#define TEMP_TO_REG(val) ((val) / 1000) -#define TEMP11_FROM_REG(reg) ((reg) / 32 * 125) - -static ssize_t show_temp11(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", TEMP11_FROM_REG(data->temp11[nr])); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])); -} - -static ssize_t show_temp_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct f75375_data *data = f75375_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[nr])); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - val = SENSORS_LIMIT(TEMP_TO_REG(val), 0, 127); - mutex_lock(&data->update_lock); - data->temp_high[nr] = val; - f75375_write8(client, F75375_REG_TEMP_HIGH(nr), data->temp_high[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_max_hyst(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct f75375_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - val = SENSORS_LIMIT(TEMP_TO_REG(val), 0, 127); - mutex_lock(&data->update_lock); - data->temp_max_hyst[nr] = val; - f75375_write8(client, F75375_REG_TEMP_HYST(nr), - data->temp_max_hyst[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_fan(thing) \ -static ssize_t show_##thing(struct device *dev, struct device_attribute *attr, \ - char *buf)\ -{\ - int nr = to_sensor_dev_attr(attr)->index;\ - struct f75375_data *data = f75375_update_device(dev); \ - return sprintf(buf, "%d\n", rpm_from_reg(data->thing[nr])); \ -} - -show_fan(fan); -show_fan(fan_min); -show_fan(fan_max); -show_fan(fan_target); - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); -static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO|S_IWUSR, - show_in_max, set_in_max, 0); -static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO|S_IWUSR, - show_in_min, set_in_min, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO|S_IWUSR, - show_in_max, set_in_max, 1); -static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO|S_IWUSR, - show_in_min, set_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO|S_IWUSR, - show_in_max, set_in_max, 2); -static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO|S_IWUSR, - show_in_min, set_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO|S_IWUSR, - show_in_max, set_in_max, 3); -static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO|S_IWUSR, - show_in_min, set_in_min, 3); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp11, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO|S_IWUSR, - show_temp_max_hyst, set_temp_max_hyst, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO|S_IWUSR, - show_temp_max, set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO|S_IWUSR, - show_temp_max_hyst, set_temp_max_hyst, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO|S_IWUSR, - show_temp_max, set_temp_max, 1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_max, S_IRUGO, show_fan_max, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO|S_IWUSR, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan1_target, S_IRUGO|S_IWUSR, - show_fan_target, set_fan_target, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_max, S_IRUGO, show_fan_max, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO|S_IWUSR, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan2_target, S_IRUGO|S_IWUSR, - show_fan_target, set_fan_target, 1); -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, - show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, - show_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, - show_pwm_mode, set_pwm_mode, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, - show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, - show_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm2_mode, S_IRUGO, - show_pwm_mode, set_pwm_mode, 1); - -static struct attribute *f75375_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_max.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_target.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_max.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_target.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_mode.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_mode.dev_attr.attr, - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - NULL -}; - -static const struct attribute_group f75375_group = { - .attrs = f75375_attributes, -}; - -static void f75375_init(struct i2c_client *client, struct f75375_data *data, - struct f75375s_platform_data *f75375s_pdata) -{ - int nr; - - if (!f75375s_pdata) { - u8 conf, mode; - int nr; - - conf = f75375_read8(client, F75375_REG_CONFIG1); - mode = f75375_read8(client, F75375_REG_FAN_TIMER); - for (nr = 0; nr < 2; nr++) { - if (data->kind == f75387) { - bool manu, duty; - - if (!(mode & (1 << F75387_FAN_CTRL_LINEAR(nr)))) - data->pwm_mode[nr] = 1; - - manu = ((mode >> F75387_FAN_MANU_MODE(nr)) & 1); - duty = ((mode >> F75387_FAN_DUTY_MODE(nr)) & 1); - if (!manu && duty) - /* auto, pwm */ - data->pwm_enable[nr] = 4; - else if (manu && !duty) - /* manual, speed */ - data->pwm_enable[nr] = 3; - else if (!manu && !duty) - /* automatic, speed */ - data->pwm_enable[nr] = 2; - else - /* manual, pwm */ - data->pwm_enable[nr] = 1; - } else { - if (!(conf & (1 << F75375_FAN_CTRL_LINEAR(nr)))) - data->pwm_mode[nr] = 1; - - switch ((mode >> FAN_CTRL_MODE(nr)) & 3) { - case 0: /* speed */ - data->pwm_enable[nr] = 3; - break; - case 1: /* automatic */ - data->pwm_enable[nr] = 2; - break; - default: /* manual */ - data->pwm_enable[nr] = 1; - break; - } - } - } - return; - } - - set_pwm_enable_direct(client, 0, f75375s_pdata->pwm_enable[0]); - set_pwm_enable_direct(client, 1, f75375s_pdata->pwm_enable[1]); - for (nr = 0; nr < 2; nr++) { - if (auto_mode_enabled(f75375s_pdata->pwm_enable[nr]) || - !duty_mode_enabled(f75375s_pdata->pwm_enable[nr])) - continue; - data->pwm[nr] = SENSORS_LIMIT(f75375s_pdata->pwm[nr], 0, 255); - f75375_write_pwm(client, nr); - } - -} - -static int f75375_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct f75375_data *data; - struct f75375s_platform_data *f75375s_pdata = client->dev.platform_data; - int err; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->kind = id->driver_data; - - err = sysfs_create_group(&client->dev.kobj, &f75375_group); - if (err) - goto exit_free; - - if (data->kind != f75373) { - err = sysfs_chmod_file(&client->dev.kobj, - &sensor_dev_attr_pwm1_mode.dev_attr.attr, - S_IRUGO | S_IWUSR); - if (err) - goto exit_remove; - err = sysfs_chmod_file(&client->dev.kobj, - &sensor_dev_attr_pwm2_mode.dev_attr.attr, - S_IRUGO | S_IWUSR); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - f75375_init(client, data, f75375s_pdata); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &f75375_group); -exit_free: - kfree(data); - return err; -} - -static int f75375_remove(struct i2c_client *client) -{ - struct f75375_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &f75375_group); - kfree(data); - return 0; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int f75375_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u16 vendid, chipid; - u8 version; - const char *name; - - vendid = f75375_read16(client, F75375_REG_VENDOR); - chipid = f75375_read16(client, F75375_CHIP_ID); - if (vendid != 0x1934) - return -ENODEV; - - if (chipid == 0x0306) - name = "f75375"; - else if (chipid == 0x0204) - name = "f75373"; - else if (chipid == 0x0410) - name = "f75387"; - else - return -ENODEV; - - version = f75375_read8(client, F75375_REG_VERSION); - dev_info(&adapter->dev, "found %s version: %02X\n", name, version); - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -module_i2c_driver(f75375_driver); - -MODULE_AUTHOR("Riku Voipio"); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("F75373/F75375/F75387 hardware monitoring driver"); diff --git a/ANDROID_3.4.5/drivers/hwmon/fam15h_power.c b/ANDROID_3.4.5/drivers/hwmon/fam15h_power.c deleted file mode 100644 index e8e18cab..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/fam15h_power.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * fam15h_power.c - AMD Family 15h processor power monitoring - * - * Copyright (c) 2011 Advanced Micro Devices, Inc. - * Author: Andreas Herrmann - * - * - * This driver is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License; either - * version 2 of the License, or (at your option) any later version. - * - * This driver 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 driver; if not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); -MODULE_AUTHOR("Andreas Herrmann "); -MODULE_LICENSE("GPL"); - -/* D18F3 */ -#define REG_NORTHBRIDGE_CAP 0xe8 - -/* D18F4 */ -#define REG_PROCESSOR_TDP 0x1b8 - -/* D18F5 */ -#define REG_TDP_RUNNING_AVERAGE 0xe0 -#define REG_TDP_LIMIT3 0xe8 - -struct fam15h_power_data { - struct device *hwmon_dev; - unsigned int tdp_to_watts; - unsigned int base_tdp; - unsigned int processor_pwr_watts; -}; - -static ssize_t show_power(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u32 val, tdp_limit, running_avg_range; - s32 running_avg_capture; - u64 curr_pwr_watts; - struct pci_dev *f4 = to_pci_dev(dev); - struct fam15h_power_data *data = dev_get_drvdata(dev); - - pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), - REG_TDP_RUNNING_AVERAGE, &val); - running_avg_capture = (val >> 4) & 0x3fffff; - running_avg_capture = sign_extend32(running_avg_capture, 21); - running_avg_range = (val & 0xf) + 1; - - pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), - REG_TDP_LIMIT3, &val); - - tdp_limit = val >> 16; - curr_pwr_watts = (tdp_limit + data->base_tdp) << running_avg_range; - curr_pwr_watts -= running_avg_capture; - curr_pwr_watts *= data->tdp_to_watts; - - /* - * Convert to microWatt - * - * power is in Watt provided as fixed point integer with - * scaling factor 1/(2^16). For conversion we use - * (10^6)/(2^16) = 15625/(2^10) - */ - curr_pwr_watts = (curr_pwr_watts * 15625) >> (10 + running_avg_range); - return sprintf(buf, "%u\n", (unsigned int) curr_pwr_watts); -} -static DEVICE_ATTR(power1_input, S_IRUGO, show_power, NULL); - -static ssize_t show_power_crit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct fam15h_power_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", data->processor_pwr_watts); -} -static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "fam15h_power\n"); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *fam15h_power_attrs[] = { - &dev_attr_power1_input.attr, - &dev_attr_power1_crit.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group fam15h_power_attr_group = { - .attrs = fam15h_power_attrs, -}; - -static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4) -{ - u32 val; - - pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 3), - REG_NORTHBRIDGE_CAP, &val); - if ((val & BIT(29)) && ((val >> 30) & 3)) - return false; - - return true; -} - -/* - * Newer BKDG versions have an updated recommendation on how to properly - * initialize the running average range (was: 0xE, now: 0x9). This avoids - * counter saturations resulting in bogus power readings. - * We correct this value ourselves to cope with older BIOSes. - */ -static DEFINE_PCI_DEVICE_TABLE(affected_device) = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, - { 0 } -}; - -static void __devinit tweak_runavg_range(struct pci_dev *pdev) -{ - u32 val; - - /* - * let this quirk apply only to the current version of the - * northbridge, since future versions may change the behavior - */ - if (!pci_match_id(affected_device, pdev)) - return; - - pci_bus_read_config_dword(pdev->bus, - PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), - REG_TDP_RUNNING_AVERAGE, &val); - if ((val & 0xf) != 0xe) - return; - - val &= ~0xf; - val |= 0x9; - pci_bus_write_config_dword(pdev->bus, - PCI_DEVFN(PCI_SLOT(pdev->devfn), 5), - REG_TDP_RUNNING_AVERAGE, val); -} - -static void __devinit fam15h_power_init_data(struct pci_dev *f4, - struct fam15h_power_data *data) -{ - u32 val; - u64 tmp; - - pci_read_config_dword(f4, REG_PROCESSOR_TDP, &val); - data->base_tdp = val >> 16; - tmp = val & 0xffff; - - pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), - REG_TDP_LIMIT3, &val); - - data->tdp_to_watts = ((val & 0x3ff) << 6) | ((val >> 10) & 0x3f); - tmp *= data->tdp_to_watts; - - /* result not allowed to be >= 256W */ - if ((tmp >> 16) >= 256) - dev_warn(&f4->dev, "Bogus value for ProcessorPwrWatts " - "(processor_pwr_watts>=%u)\n", - (unsigned int) (tmp >> 16)); - - /* convert to microWatt */ - data->processor_pwr_watts = (tmp * 15625) >> 10; -} - -static int __devinit fam15h_power_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct fam15h_power_data *data; - struct device *dev; - int err; - - /* - * though we ignore every other northbridge, we still have to - * do the tweaking on _each_ node in MCM processors as the counters - * are working hand-in-hand - */ - tweak_runavg_range(pdev); - - if (!fam15h_power_is_internal_node0(pdev)) { - err = -ENODEV; - goto exit; - } - - data = kzalloc(sizeof(struct fam15h_power_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - fam15h_power_init_data(pdev, data); - dev = &pdev->dev; - - dev_set_drvdata(dev, data); - err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group); - if (err) - goto exit_free_data; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_group; - } - - return 0; - -exit_remove_group: - sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); -exit_free_data: - kfree(data); -exit: - return err; -} - -static void __devexit fam15h_power_remove(struct pci_dev *pdev) -{ - struct device *dev; - struct fam15h_power_data *data; - - dev = &pdev->dev; - data = dev_get_drvdata(dev); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); - dev_set_drvdata(dev, NULL); - kfree(data); -} - -static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, - {} -}; -MODULE_DEVICE_TABLE(pci, fam15h_power_id_table); - -static struct pci_driver fam15h_power_driver = { - .name = "fam15h_power", - .id_table = fam15h_power_id_table, - .probe = fam15h_power_probe, - .remove = __devexit_p(fam15h_power_remove), -}; - -static int __init fam15h_power_init(void) -{ - return pci_register_driver(&fam15h_power_driver); -} - -static void __exit fam15h_power_exit(void) -{ - pci_unregister_driver(&fam15h_power_driver); -} - -module_init(fam15h_power_init) -module_exit(fam15h_power_exit) diff --git a/ANDROID_3.4.5/drivers/hwmon/fschmd.c b/ANDROID_3.4.5/drivers/hwmon/fschmd.c deleted file mode 100644 index 519ce8b9..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/fschmd.c +++ /dev/null @@ -1,1388 +0,0 @@ -/* - * fschmd.c - * - * Copyright (C) 2007 - 2009 Hans de Goede - * - * 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. - */ - -/* - * Merged Fujitsu Siemens hwmon driver, supporting the Poseidon, Hermes, - * Scylla, Heracles, Heimdall, Hades and Syleus chips - * - * Based on the original 2.4 fscscy, 2.6 fscpos, 2.6 fscher and 2.6 - * (candidate) fschmd drivers: - * Copyright (C) 2006 Thilo Cestonaro - * - * Copyright (C) 2004, 2005 Stefan Ott - * Copyright (C) 2003, 2004 Reinhard Nissl - * Copyright (c) 2001 Martin Knoblauch - * Copyright (C) 2000 Hermann Jung - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x73, I2C_CLIENT_END }; - -/* Insmod parameters */ -static bool nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -enum chips { fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl }; - -/* - * The FSCHMD registers and other defines - */ - -/* chip identification */ -#define FSCHMD_REG_IDENT_0 0x00 -#define FSCHMD_REG_IDENT_1 0x01 -#define FSCHMD_REG_IDENT_2 0x02 -#define FSCHMD_REG_REVISION 0x03 - -/* global control and status */ -#define FSCHMD_REG_EVENT_STATE 0x04 -#define FSCHMD_REG_CONTROL 0x05 - -#define FSCHMD_CONTROL_ALERT_LED 0x01 - -/* watchdog */ -static const u8 FSCHMD_REG_WDOG_CONTROL[7] = { - 0x21, 0x21, 0x21, 0x21, 0x21, 0x28, 0x28 }; -static const u8 FSCHMD_REG_WDOG_STATE[7] = { - 0x23, 0x23, 0x23, 0x23, 0x23, 0x29, 0x29 }; -static const u8 FSCHMD_REG_WDOG_PRESET[7] = { - 0x28, 0x28, 0x28, 0x28, 0x28, 0x2a, 0x2a }; - -#define FSCHMD_WDOG_CONTROL_TRIGGER 0x10 -#define FSCHMD_WDOG_CONTROL_STARTED 0x10 /* the same as trigger */ -#define FSCHMD_WDOG_CONTROL_STOP 0x20 -#define FSCHMD_WDOG_CONTROL_RESOLUTION 0x40 - -#define FSCHMD_WDOG_STATE_CARDRESET 0x02 - -/* voltages, weird order is to keep the same order as the old drivers */ -static const u8 FSCHMD_REG_VOLT[7][6] = { - { 0x45, 0x42, 0x48 }, /* pos */ - { 0x45, 0x42, 0x48 }, /* her */ - { 0x45, 0x42, 0x48 }, /* scy */ - { 0x45, 0x42, 0x48 }, /* hrc */ - { 0x45, 0x42, 0x48 }, /* hmd */ - { 0x21, 0x20, 0x22 }, /* hds */ - { 0x21, 0x20, 0x22, 0x23, 0x24, 0x25 }, /* syl */ -}; - -static const int FSCHMD_NO_VOLT_SENSORS[7] = { 3, 3, 3, 3, 3, 3, 6 }; - -/* - * minimum pwm at which the fan is driven (pwm can by increased depending on - * the temp. Notice that for the scy some fans share there minimum speed. - * Also notice that with the scy the sensor order is different than with the - * other chips, this order was in the 2.4 driver and kept for consistency. - */ -static const u8 FSCHMD_REG_FAN_MIN[7][7] = { - { 0x55, 0x65 }, /* pos */ - { 0x55, 0x65, 0xb5 }, /* her */ - { 0x65, 0x65, 0x55, 0xa5, 0x55, 0xa5 }, /* scy */ - { 0x55, 0x65, 0xa5, 0xb5 }, /* hrc */ - { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hmd */ - { 0x55, 0x65, 0xa5, 0xb5, 0xc5 }, /* hds */ - { 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb4 }, /* syl */ -}; - -/* actual fan speed */ -static const u8 FSCHMD_REG_FAN_ACT[7][7] = { - { 0x0e, 0x6b, 0xab }, /* pos */ - { 0x0e, 0x6b, 0xbb }, /* her */ - { 0x6b, 0x6c, 0x0e, 0xab, 0x5c, 0xbb }, /* scy */ - { 0x0e, 0x6b, 0xab, 0xbb }, /* hrc */ - { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hmd */ - { 0x5b, 0x6b, 0xab, 0xbb, 0xcb }, /* hds */ - { 0x57, 0x67, 0x77, 0x87, 0x97, 0xa7, 0xb7 }, /* syl */ -}; - -/* fan status registers */ -static const u8 FSCHMD_REG_FAN_STATE[7][7] = { - { 0x0d, 0x62, 0xa2 }, /* pos */ - { 0x0d, 0x62, 0xb2 }, /* her */ - { 0x62, 0x61, 0x0d, 0xa2, 0x52, 0xb2 }, /* scy */ - { 0x0d, 0x62, 0xa2, 0xb2 }, /* hrc */ - { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hmd */ - { 0x52, 0x62, 0xa2, 0xb2, 0xc2 }, /* hds */ - { 0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0 }, /* syl */ -}; - -/* fan ripple / divider registers */ -static const u8 FSCHMD_REG_FAN_RIPPLE[7][7] = { - { 0x0f, 0x6f, 0xaf }, /* pos */ - { 0x0f, 0x6f, 0xbf }, /* her */ - { 0x6f, 0x6f, 0x0f, 0xaf, 0x0f, 0xbf }, /* scy */ - { 0x0f, 0x6f, 0xaf, 0xbf }, /* hrc */ - { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hmd */ - { 0x5f, 0x6f, 0xaf, 0xbf, 0xcf }, /* hds */ - { 0x56, 0x66, 0x76, 0x86, 0x96, 0xa6, 0xb6 }, /* syl */ -}; - -static const int FSCHMD_NO_FAN_SENSORS[7] = { 3, 3, 6, 4, 5, 5, 7 }; - -/* Fan status register bitmasks */ -#define FSCHMD_FAN_ALARM 0x04 /* called fault by FSC! */ -#define FSCHMD_FAN_NOT_PRESENT 0x08 -#define FSCHMD_FAN_DISABLED 0x80 - - -/* actual temperature registers */ -static const u8 FSCHMD_REG_TEMP_ACT[7][11] = { - { 0x64, 0x32, 0x35 }, /* pos */ - { 0x64, 0x32, 0x35 }, /* her */ - { 0x64, 0xD0, 0x32, 0x35 }, /* scy */ - { 0x64, 0x32, 0x35 }, /* hrc */ - { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hmd */ - { 0x70, 0x80, 0x90, 0xd0, 0xe0 }, /* hds */ - { 0x58, 0x68, 0x78, 0x88, 0x98, 0xa8, /* syl */ - 0xb8, 0xc8, 0xd8, 0xe8, 0xf8 }, -}; - -/* temperature state registers */ -static const u8 FSCHMD_REG_TEMP_STATE[7][11] = { - { 0x71, 0x81, 0x91 }, /* pos */ - { 0x71, 0x81, 0x91 }, /* her */ - { 0x71, 0xd1, 0x81, 0x91 }, /* scy */ - { 0x71, 0x81, 0x91 }, /* hrc */ - { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hmd */ - { 0x71, 0x81, 0x91, 0xd1, 0xe1 }, /* hds */ - { 0x59, 0x69, 0x79, 0x89, 0x99, 0xa9, /* syl */ - 0xb9, 0xc9, 0xd9, 0xe9, 0xf9 }, -}; - -/* - * temperature high limit registers, FSC does not document these. Proven to be - * there with field testing on the fscher and fschrc, already supported / used - * in the fscscy 2.4 driver. FSC has confirmed that the fschmd has registers - * at these addresses, but doesn't want to confirm they are the same as with - * the fscher?? - */ -static const u8 FSCHMD_REG_TEMP_LIMIT[7][11] = { - { 0, 0, 0 }, /* pos */ - { 0x76, 0x86, 0x96 }, /* her */ - { 0x76, 0xd6, 0x86, 0x96 }, /* scy */ - { 0x76, 0x86, 0x96 }, /* hrc */ - { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hmd */ - { 0x76, 0x86, 0x96, 0xd6, 0xe6 }, /* hds */ - { 0x5a, 0x6a, 0x7a, 0x8a, 0x9a, 0xaa, /* syl */ - 0xba, 0xca, 0xda, 0xea, 0xfa }, -}; - -/* - * These were found through experimenting with an fscher, currently they are - * not used, but we keep them around for future reference. - * On the fscsyl AUTOP1 lives at 0x#c (so 0x5c for fan1, 0x6c for fan2, etc), - * AUTOP2 lives at 0x#e, and 0x#1 is a bitmask defining which temps influence - * the fan speed. - * static const u8 FSCHER_REG_TEMP_AUTOP1[] = { 0x73, 0x83, 0x93 }; - * static const u8 FSCHER_REG_TEMP_AUTOP2[] = { 0x75, 0x85, 0x95 }; - */ - -static const int FSCHMD_NO_TEMP_SENSORS[7] = { 3, 3, 4, 3, 5, 5, 11 }; - -/* temp status register bitmasks */ -#define FSCHMD_TEMP_WORKING 0x01 -#define FSCHMD_TEMP_ALERT 0x02 -#define FSCHMD_TEMP_DISABLED 0x80 -/* there only really is an alarm if the sensor is working and alert == 1 */ -#define FSCHMD_TEMP_ALARM_MASK \ - (FSCHMD_TEMP_WORKING | FSCHMD_TEMP_ALERT) - -/* - * Functions declarations - */ - -static int fschmd_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int fschmd_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int fschmd_remove(struct i2c_client *client); -static struct fschmd_data *fschmd_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id fschmd_id[] = { - { "fscpos", fscpos }, - { "fscher", fscher }, - { "fscscy", fscscy }, - { "fschrc", fschrc }, - { "fschmd", fschmd }, - { "fschds", fschds }, - { "fscsyl", fscsyl }, - { } -}; -MODULE_DEVICE_TABLE(i2c, fschmd_id); - -static struct i2c_driver fschmd_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "fschmd", - }, - .probe = fschmd_probe, - .remove = fschmd_remove, - .id_table = fschmd_id, - .detect = fschmd_detect, - .address_list = normal_i2c, -}; - -/* - * Client data (each client gets its own) - */ - -struct fschmd_data { - struct i2c_client *client; - struct device *hwmon_dev; - struct mutex update_lock; - struct mutex watchdog_lock; - struct list_head list; /* member of the watchdog_data_list */ - struct kref kref; - struct miscdevice watchdog_miscdev; - enum chips kind; - unsigned long watchdog_is_open; - char watchdog_expect_close; - char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* register values */ - u8 revision; /* chip revision */ - u8 global_control; /* global control register */ - u8 watchdog_control; /* watchdog control register */ - u8 watchdog_state; /* watchdog status register */ - u8 watchdog_preset; /* watchdog counter preset on trigger val */ - u8 volt[6]; /* voltage */ - u8 temp_act[11]; /* temperature */ - u8 temp_status[11]; /* status of sensor */ - u8 temp_max[11]; /* high temp limit, notice: undocumented! */ - u8 fan_act[7]; /* fans revolutions per second */ - u8 fan_status[7]; /* fan status */ - u8 fan_min[7]; /* fan min value for rps */ - u8 fan_ripple[7]; /* divider for rps */ -}; - -/* - * Global variables to hold information read from special DMI tables, which are - * available on FSC machines with an fscher or later chip. There is no need to - * protect these with a lock as they are only modified from our attach function - * which always gets called with the i2c-core lock held and never accessed - * before the attach function is done with them. - */ -static int dmi_mult[6] = { 490, 200, 100, 100, 200, 100 }; -static int dmi_offset[6] = { 0, 0, 0, 0, 0, 0 }; -static int dmi_vref = -1; - -/* - * Somewhat ugly :( global data pointer list with all fschmd devices, so that - * we can find our device data as when using misc_register there is no other - * method to get to ones device data from the open fop. - */ -static LIST_HEAD(watchdog_data_list); -/* Note this lock not only protect list access, but also data.kref access */ -static DEFINE_MUTEX(watchdog_data_mutex); - -/* - * Release our data struct when we're detached from the i2c client *and* all - * references to our watchdog device are released - */ -static void fschmd_release_resources(struct kref *ref) -{ - struct fschmd_data *data = container_of(ref, struct fschmd_data, kref); - kfree(data); -} - -/* - * Sysfs attr show / store functions - */ - -static ssize_t show_in_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - const int max_reading[3] = { 14200, 6600, 3300 }; - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - if (data->kind == fscher || data->kind >= fschrc) - return sprintf(buf, "%d\n", (data->volt[index] * dmi_vref * - dmi_mult[index]) / 255 + dmi_offset[index]); - else - return sprintf(buf, "%d\n", (data->volt[index] * - max_reading[index] + 128) / 255); -} - - -#define TEMP_FROM_REG(val) (((val) - 128) * 1000) - -static ssize_t show_temp_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_act[index])); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[index])); -} - -static ssize_t store_temp_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = dev_get_drvdata(dev); - long v; - int err; - - err = kstrtol(buf, 10, &v); - if (err) - return err; - - v = SENSORS_LIMIT(v / 1000, -128, 127) + 128; - - mutex_lock(&data->update_lock); - i2c_smbus_write_byte_data(to_i2c_client(dev), - FSCHMD_REG_TEMP_LIMIT[data->kind][index], v); - data->temp_max[index] = v; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp_fault(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - /* bit 0 set means sensor working ok, so no fault! */ - if (data->temp_status[index] & FSCHMD_TEMP_WORKING) - return sprintf(buf, "0\n"); - else - return sprintf(buf, "1\n"); -} - -static ssize_t show_temp_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - if ((data->temp_status[index] & FSCHMD_TEMP_ALARM_MASK) == - FSCHMD_TEMP_ALARM_MASK) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - - -#define RPM_FROM_REG(val) ((val) * 60) - -static ssize_t show_fan_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - return sprintf(buf, "%u\n", RPM_FROM_REG(data->fan_act[index])); -} - -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - /* bits 2..7 reserved => mask with 3 */ - return sprintf(buf, "%d\n", 1 << (data->fan_ripple[index] & 3)); -} - -static ssize_t store_fan_div(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - u8 reg; - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = dev_get_drvdata(dev); - /* supported values: 2, 4, 8 */ - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - switch (v) { - case 2: - v = 1; - break; - case 4: - v = 2; - break; - case 8: - v = 3; - break; - default: - dev_err(dev, "fan_div value %lu not supported. " - "Choose one of 2, 4 or 8!\n", v); - return -EINVAL; - } - - mutex_lock(&data->update_lock); - - reg = i2c_smbus_read_byte_data(to_i2c_client(dev), - FSCHMD_REG_FAN_RIPPLE[data->kind][index]); - - /* bits 2..7 reserved => mask with 0x03 */ - reg &= ~0x03; - reg |= v; - - i2c_smbus_write_byte_data(to_i2c_client(dev), - FSCHMD_REG_FAN_RIPPLE[data->kind][index], reg); - - data->fan_ripple[index] = reg; - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_fan_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - if (data->fan_status[index] & FSCHMD_FAN_ALARM) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t show_fan_fault(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - - if (data->fan_status[index] & FSCHMD_FAN_NOT_PRESENT) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - - -static ssize_t show_pwm_auto_point1_pwm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = fschmd_update_device(dev); - int val = data->fan_min[index]; - - /* 0 = allow turning off (except on the syl), 1-255 = 50-100% */ - if (val || data->kind == fscsyl) - val = val / 2 + 128; - - return sprintf(buf, "%d\n", val); -} - -static ssize_t store_pwm_auto_point1_pwm(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct fschmd_data *data = dev_get_drvdata(dev); - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - /* reg: 0 = allow turning off (except on the syl), 1-255 = 50-100% */ - if (v || data->kind == fscsyl) { - v = SENSORS_LIMIT(v, 128, 255); - v = (v - 128) * 2 + 1; - } - - mutex_lock(&data->update_lock); - - i2c_smbus_write_byte_data(to_i2c_client(dev), - FSCHMD_REG_FAN_MIN[data->kind][index], v); - data->fan_min[index] = v; - - mutex_unlock(&data->update_lock); - - return count; -} - - -/* - * The FSC hwmon family has the ability to force an attached alert led to flash - * from software, we export this as an alert_led sysfs attr - */ -static ssize_t show_alert_led(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct fschmd_data *data = fschmd_update_device(dev); - - if (data->global_control & FSCHMD_CONTROL_ALERT_LED) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_alert_led(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - u8 reg; - struct fschmd_data *data = dev_get_drvdata(dev); - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - mutex_lock(&data->update_lock); - - reg = i2c_smbus_read_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL); - - if (v) - reg |= FSCHMD_CONTROL_ALERT_LED; - else - reg &= ~FSCHMD_CONTROL_ALERT_LED; - - i2c_smbus_write_byte_data(to_i2c_client(dev), FSCHMD_REG_CONTROL, reg); - - data->global_control = reg; - - mutex_unlock(&data->update_lock); - - return count; -} - -static DEVICE_ATTR(alert_led, 0644, show_alert_led, store_alert_led); - -static struct sensor_device_attribute fschmd_attr[] = { - SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), - SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), - SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), - SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3), - SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4), - SENSOR_ATTR(in5_input, 0444, show_in_value, NULL, 5), -}; - -static struct sensor_device_attribute fschmd_temp_attr[] = { - SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), - SENSOR_ATTR(temp1_max, 0644, show_temp_max, store_temp_max, 0), - SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0), - SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0), - SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1), - SENSOR_ATTR(temp2_max, 0644, show_temp_max, store_temp_max, 1), - SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1), - SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1), - SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2), - SENSOR_ATTR(temp3_max, 0644, show_temp_max, store_temp_max, 2), - SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2), - SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2), - SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3), - SENSOR_ATTR(temp4_max, 0644, show_temp_max, store_temp_max, 3), - SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3), - SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3), - SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4), - SENSOR_ATTR(temp5_max, 0644, show_temp_max, store_temp_max, 4), - SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), - SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), - SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5), - SENSOR_ATTR(temp6_max, 0644, show_temp_max, store_temp_max, 5), - SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5), - SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5), - SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6), - SENSOR_ATTR(temp7_max, 0644, show_temp_max, store_temp_max, 6), - SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6), - SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6), - SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7), - SENSOR_ATTR(temp8_max, 0644, show_temp_max, store_temp_max, 7), - SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7), - SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7), - SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8), - SENSOR_ATTR(temp9_max, 0644, show_temp_max, store_temp_max, 8), - SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8), - SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8), - SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9), - SENSOR_ATTR(temp10_max, 0644, show_temp_max, store_temp_max, 9), - SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9), - SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9), - SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10), - SENSOR_ATTR(temp11_max, 0644, show_temp_max, store_temp_max, 10), - SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10), - SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10), -}; - -static struct sensor_device_attribute fschmd_fan_attr[] = { - SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0), - SENSOR_ATTR(fan1_div, 0644, show_fan_div, store_fan_div, 0), - SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0), - SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0), - SENSOR_ATTR(pwm1_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 0), - SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1), - SENSOR_ATTR(fan2_div, 0644, show_fan_div, store_fan_div, 1), - SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1), - SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1), - SENSOR_ATTR(pwm2_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 1), - SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2), - SENSOR_ATTR(fan3_div, 0644, show_fan_div, store_fan_div, 2), - SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2), - SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2), - SENSOR_ATTR(pwm3_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 2), - SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3), - SENSOR_ATTR(fan4_div, 0644, show_fan_div, store_fan_div, 3), - SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3), - SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3), - SENSOR_ATTR(pwm4_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 3), - SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4), - SENSOR_ATTR(fan5_div, 0644, show_fan_div, store_fan_div, 4), - SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4), - SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4), - SENSOR_ATTR(pwm5_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 4), - SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5), - SENSOR_ATTR(fan6_div, 0644, show_fan_div, store_fan_div, 5), - SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5), - SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), - SENSOR_ATTR(pwm6_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 5), - SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6), - SENSOR_ATTR(fan7_div, 0644, show_fan_div, store_fan_div, 6), - SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6), - SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6), - SENSOR_ATTR(pwm7_auto_point1_pwm, 0644, show_pwm_auto_point1_pwm, - store_pwm_auto_point1_pwm, 6), -}; - - -/* - * Watchdog routines - */ - -static int watchdog_set_timeout(struct fschmd_data *data, int timeout) -{ - int ret, resolution; - int kind = data->kind + 1; /* 0-x array index -> 1-x module param */ - - /* 2 second or 60 second resolution? */ - if (timeout <= 510 || kind == fscpos || kind == fscscy) - resolution = 2; - else - resolution = 60; - - if (timeout < resolution || timeout > (resolution * 255)) - return -EINVAL; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - if (resolution == 2) - data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_RESOLUTION; - else - data->watchdog_control |= FSCHMD_WDOG_CONTROL_RESOLUTION; - - data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); - - /* Write new timeout value */ - i2c_smbus_write_byte_data(data->client, - FSCHMD_REG_WDOG_PRESET[data->kind], data->watchdog_preset); - /* Write new control register, do not trigger! */ - i2c_smbus_write_byte_data(data->client, - FSCHMD_REG_WDOG_CONTROL[data->kind], - data->watchdog_control & ~FSCHMD_WDOG_CONTROL_TRIGGER); - - ret = data->watchdog_preset * resolution; - -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_get_timeout(struct fschmd_data *data) -{ - int timeout; - - mutex_lock(&data->watchdog_lock); - if (data->watchdog_control & FSCHMD_WDOG_CONTROL_RESOLUTION) - timeout = data->watchdog_preset * 60; - else - timeout = data->watchdog_preset * 2; - mutex_unlock(&data->watchdog_lock); - - return timeout; -} - -static int watchdog_trigger(struct fschmd_data *data) -{ - int ret = 0; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - data->watchdog_control |= FSCHMD_WDOG_CONTROL_TRIGGER; - i2c_smbus_write_byte_data(data->client, - FSCHMD_REG_WDOG_CONTROL[data->kind], - data->watchdog_control); -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_stop(struct fschmd_data *data) -{ - int ret = 0; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - data->watchdog_control &= ~FSCHMD_WDOG_CONTROL_STARTED; - /* - * Don't store the stop flag in our watchdog control register copy, as - * its a write only bit (read always returns 0) - */ - i2c_smbus_write_byte_data(data->client, - FSCHMD_REG_WDOG_CONTROL[data->kind], - data->watchdog_control | FSCHMD_WDOG_CONTROL_STOP); -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_open(struct inode *inode, struct file *filp) -{ - struct fschmd_data *pos, *data = NULL; - int watchdog_is_open; - - /* - * We get called from drivers/char/misc.c with misc_mtx hold, and we - * call misc_register() from fschmd_probe() with watchdog_data_mutex - * hold, as misc_register() takes the misc_mtx lock, this is a possible - * deadlock, so we use mutex_trylock here. - */ - if (!mutex_trylock(&watchdog_data_mutex)) - return -ERESTARTSYS; - list_for_each_entry(pos, &watchdog_data_list, list) { - if (pos->watchdog_miscdev.minor == iminor(inode)) { - data = pos; - break; - } - } - /* Note we can never not have found data, so we don't check for this */ - watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open); - if (!watchdog_is_open) - kref_get(&data->kref); - mutex_unlock(&watchdog_data_mutex); - - if (watchdog_is_open) - return -EBUSY; - - /* Start the watchdog */ - watchdog_trigger(data); - filp->private_data = data; - - return nonseekable_open(inode, filp); -} - -static int watchdog_release(struct inode *inode, struct file *filp) -{ - struct fschmd_data *data = filp->private_data; - - if (data->watchdog_expect_close) { - watchdog_stop(data); - data->watchdog_expect_close = 0; - } else { - watchdog_trigger(data); - dev_crit(&data->client->dev, - "unexpected close, not stopping watchdog!\n"); - } - - clear_bit(0, &data->watchdog_is_open); - - mutex_lock(&watchdog_data_mutex); - kref_put(&data->kref, fschmd_release_resources); - mutex_unlock(&watchdog_data_mutex); - - return 0; -} - -static ssize_t watchdog_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) -{ - int ret; - struct fschmd_data *data = filp->private_data; - - if (count) { - if (!nowayout) { - size_t i; - - /* Clear it in case it was set with a previous write */ - data->watchdog_expect_close = 0; - - for (i = 0; i != count; i++) { - char c; - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - data->watchdog_expect_close = 1; - } - } - ret = watchdog_trigger(data); - if (ret < 0) - return ret; - } - return count; -} - -static long watchdog_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | - WDIOF_CARDRESET, - .identity = "FSC watchdog" - }; - int i, ret = 0; - struct fschmd_data *data = filp->private_data; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ident.firmware_version = data->revision; - if (!nowayout) - ident.options |= WDIOF_MAGICCLOSE; - if (copy_to_user((void __user *)arg, &ident, sizeof(ident))) - ret = -EFAULT; - break; - - case WDIOC_GETSTATUS: - ret = put_user(0, (int __user *)arg); - break; - - case WDIOC_GETBOOTSTATUS: - if (data->watchdog_state & FSCHMD_WDOG_STATE_CARDRESET) - ret = put_user(WDIOF_CARDRESET, (int __user *)arg); - else - ret = put_user(0, (int __user *)arg); - break; - - case WDIOC_KEEPALIVE: - ret = watchdog_trigger(data); - break; - - case WDIOC_GETTIMEOUT: - i = watchdog_get_timeout(data); - ret = put_user(i, (int __user *)arg); - break; - - case WDIOC_SETTIMEOUT: - if (get_user(i, (int __user *)arg)) { - ret = -EFAULT; - break; - } - ret = watchdog_set_timeout(data, i); - if (ret > 0) - ret = put_user(ret, (int __user *)arg); - break; - - case WDIOC_SETOPTIONS: - if (get_user(i, (int __user *)arg)) { - ret = -EFAULT; - break; - } - - if (i & WDIOS_DISABLECARD) - ret = watchdog_stop(data); - else if (i & WDIOS_ENABLECARD) - ret = watchdog_trigger(data); - else - ret = -EINVAL; - - break; - default: - ret = -ENOTTY; - } - return ret; -} - -static const struct file_operations watchdog_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .open = watchdog_open, - .release = watchdog_release, - .write = watchdog_write, - .unlocked_ioctl = watchdog_ioctl, -}; - - -/* - * Detect, register, unregister and update device functions - */ - -/* - * DMI decode routine to read voltage scaling factors from special DMI tables, - * which are available on FSC machines with an fscher or later chip. - */ -static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy) -{ - int i, mult[3] = { 0 }, offset[3] = { 0 }, vref = 0, found = 0; - - /* - * dmi code ugliness, we get passed the address of the contents of - * a complete DMI record, but in the form of a dmi_header pointer, in - * reality this address holds header->length bytes of which the header - * are the first 4 bytes - */ - u8 *dmi_data = (u8 *)header; - - /* We are looking for OEM-specific type 185 */ - if (header->type != 185) - return; - - /* - * we are looking for what Siemens calls "subtype" 19, the subtype - * is stored in byte 5 of the dmi block - */ - if (header->length < 5 || dmi_data[4] != 19) - return; - - /* - * After the subtype comes 1 unknown byte and then blocks of 5 bytes, - * consisting of what Siemens calls an "Entity" number, followed by - * 2 16-bit words in LSB first order - */ - for (i = 6; (i + 4) < header->length; i += 5) { - /* entity 1 - 3: voltage multiplier and offset */ - if (dmi_data[i] >= 1 && dmi_data[i] <= 3) { - /* Our in sensors order and the DMI order differ */ - const int shuffle[3] = { 1, 0, 2 }; - int in = shuffle[dmi_data[i] - 1]; - - /* Check for twice the same entity */ - if (found & (1 << in)) - return; - - mult[in] = dmi_data[i + 1] | (dmi_data[i + 2] << 8); - offset[in] = dmi_data[i + 3] | (dmi_data[i + 4] << 8); - - found |= 1 << in; - } - - /* entity 7: reference voltage */ - if (dmi_data[i] == 7) { - /* Check for twice the same entity */ - if (found & 0x08) - return; - - vref = dmi_data[i + 1] | (dmi_data[i + 2] << 8); - - found |= 0x08; - } - } - - if (found == 0x0F) { - for (i = 0; i < 3; i++) { - dmi_mult[i] = mult[i] * 10; - dmi_offset[i] = offset[i] * 10; - } - /* - * According to the docs there should be separate dmi entries - * for the mult's and offsets of in3-5 of the syl, but on - * my test machine these are not present - */ - dmi_mult[3] = dmi_mult[2]; - dmi_mult[4] = dmi_mult[1]; - dmi_mult[5] = dmi_mult[2]; - dmi_offset[3] = dmi_offset[2]; - dmi_offset[4] = dmi_offset[1]; - dmi_offset[5] = dmi_offset[2]; - dmi_vref = vref; - } -} - -static int fschmd_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - enum chips kind; - struct i2c_adapter *adapter = client->adapter; - char id[4]; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Detect & Identify the chip */ - id[0] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_0); - id[1] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_1); - id[2] = i2c_smbus_read_byte_data(client, FSCHMD_REG_IDENT_2); - id[3] = '\0'; - - if (!strcmp(id, "PEG")) - kind = fscpos; - else if (!strcmp(id, "HER")) - kind = fscher; - else if (!strcmp(id, "SCY")) - kind = fscscy; - else if (!strcmp(id, "HRC")) - kind = fschrc; - else if (!strcmp(id, "HMD")) - kind = fschmd; - else if (!strcmp(id, "HDS")) - kind = fschds; - else if (!strcmp(id, "SYL")) - kind = fscsyl; - else - return -ENODEV; - - strlcpy(info->type, fschmd_id[kind].name, I2C_NAME_SIZE); - - return 0; -} - -static int fschmd_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct fschmd_data *data; - const char * const names[7] = { "Poseidon", "Hermes", "Scylla", - "Heracles", "Heimdall", "Hades", "Syleus" }; - const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; - int i, err; - enum chips kind = id->driver_data; - - data = kzalloc(sizeof(struct fschmd_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - mutex_init(&data->watchdog_lock); - INIT_LIST_HEAD(&data->list); - kref_init(&data->kref); - /* - * Store client pointer in our data struct for watchdog usage - * (where the client is found through a data ptr instead of the - * otherway around) - */ - data->client = client; - data->kind = kind; - - if (kind == fscpos) { - /* - * The Poseidon has hardwired temp limits, fill these - * in for the alarm resetting code - */ - data->temp_max[0] = 70 + 128; - data->temp_max[1] = 50 + 128; - data->temp_max[2] = 50 + 128; - } - - /* Read the special DMI table for fscher and newer chips */ - if ((kind == fscher || kind >= fschrc) && dmi_vref == -1) { - dmi_walk(fschmd_dmi_decode, NULL); - if (dmi_vref == -1) { - dev_warn(&client->dev, - "Couldn't get voltage scaling factors from " - "BIOS DMI table, using builtin defaults\n"); - dmi_vref = 33; - } - } - - /* Read in some never changing registers */ - data->revision = i2c_smbus_read_byte_data(client, FSCHMD_REG_REVISION); - data->global_control = i2c_smbus_read_byte_data(client, - FSCHMD_REG_CONTROL); - data->watchdog_control = i2c_smbus_read_byte_data(client, - FSCHMD_REG_WDOG_CONTROL[data->kind]); - data->watchdog_state = i2c_smbus_read_byte_data(client, - FSCHMD_REG_WDOG_STATE[data->kind]); - data->watchdog_preset = i2c_smbus_read_byte_data(client, - FSCHMD_REG_WDOG_PRESET[data->kind]); - - err = device_create_file(&client->dev, &dev_attr_alert_led); - if (err) - goto exit_detach; - - for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++) { - err = device_create_file(&client->dev, - &fschmd_attr[i].dev_attr); - if (err) - goto exit_detach; - } - - for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) { - /* Poseidon doesn't have TEMP_LIMIT registers */ - if (kind == fscpos && fschmd_temp_attr[i].dev_attr.show == - show_temp_max) - continue; - - if (kind == fscsyl) { - if (i % 4 == 0) - data->temp_status[i / 4] = - i2c_smbus_read_byte_data(client, - FSCHMD_REG_TEMP_STATE - [data->kind][i / 4]); - if (data->temp_status[i / 4] & FSCHMD_TEMP_DISABLED) - continue; - } - - err = device_create_file(&client->dev, - &fschmd_temp_attr[i].dev_attr); - if (err) - goto exit_detach; - } - - for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++) { - /* Poseidon doesn't have a FAN_MIN register for its 3rd fan */ - if (kind == fscpos && - !strcmp(fschmd_fan_attr[i].dev_attr.attr.name, - "pwm3_auto_point1_pwm")) - continue; - - if (kind == fscsyl) { - if (i % 5 == 0) - data->fan_status[i / 5] = - i2c_smbus_read_byte_data(client, - FSCHMD_REG_FAN_STATE - [data->kind][i / 5]); - if (data->fan_status[i / 5] & FSCHMD_FAN_DISABLED) - continue; - } - - err = device_create_file(&client->dev, - &fschmd_fan_attr[i].dev_attr); - if (err) - goto exit_detach; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - data->hwmon_dev = NULL; - goto exit_detach; - } - - /* - * We take the data_mutex lock early so that watchdog_open() cannot - * run when misc_register() has completed, but we've not yet added - * our data to the watchdog_data_list (and set the default timeout) - */ - mutex_lock(&watchdog_data_mutex); - for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) { - /* Register our watchdog part */ - snprintf(data->watchdog_name, sizeof(data->watchdog_name), - "watchdog%c", (i == 0) ? '\0' : ('0' + i)); - data->watchdog_miscdev.name = data->watchdog_name; - data->watchdog_miscdev.fops = &watchdog_fops; - data->watchdog_miscdev.minor = watchdog_minors[i]; - err = misc_register(&data->watchdog_miscdev); - if (err == -EBUSY) - continue; - if (err) { - data->watchdog_miscdev.minor = 0; - dev_err(&client->dev, - "Registering watchdog chardev: %d\n", err); - break; - } - - list_add(&data->list, &watchdog_data_list); - watchdog_set_timeout(data, 60); - dev_info(&client->dev, - "Registered watchdog chardev major 10, minor: %d\n", - watchdog_minors[i]); - break; - } - if (i == ARRAY_SIZE(watchdog_minors)) { - data->watchdog_miscdev.minor = 0; - dev_warn(&client->dev, "Couldn't register watchdog chardev " - "(due to no free minor)\n"); - } - mutex_unlock(&watchdog_data_mutex); - - dev_info(&client->dev, "Detected FSC %s chip, revision: %d\n", - names[data->kind], (int) data->revision); - - return 0; - -exit_detach: - fschmd_remove(client); /* will also free data for us */ - return err; -} - -static int fschmd_remove(struct i2c_client *client) -{ - struct fschmd_data *data = i2c_get_clientdata(client); - int i; - - /* Unregister the watchdog (if registered) */ - if (data->watchdog_miscdev.minor) { - misc_deregister(&data->watchdog_miscdev); - if (data->watchdog_is_open) { - dev_warn(&client->dev, - "i2c client detached with watchdog open! " - "Stopping watchdog.\n"); - watchdog_stop(data); - } - mutex_lock(&watchdog_data_mutex); - list_del(&data->list); - mutex_unlock(&watchdog_data_mutex); - /* Tell the watchdog code the client is gone */ - mutex_lock(&data->watchdog_lock); - data->client = NULL; - mutex_unlock(&data->watchdog_lock); - } - - /* - * Check if registered in case we're called from fschmd_detect - * to cleanup after an error - */ - if (data->hwmon_dev) - hwmon_device_unregister(data->hwmon_dev); - - device_remove_file(&client->dev, &dev_attr_alert_led); - for (i = 0; i < (FSCHMD_NO_VOLT_SENSORS[data->kind]); i++) - device_remove_file(&client->dev, &fschmd_attr[i].dev_attr); - for (i = 0; i < (FSCHMD_NO_TEMP_SENSORS[data->kind] * 4); i++) - device_remove_file(&client->dev, - &fschmd_temp_attr[i].dev_attr); - for (i = 0; i < (FSCHMD_NO_FAN_SENSORS[data->kind] * 5); i++) - device_remove_file(&client->dev, - &fschmd_fan_attr[i].dev_attr); - - mutex_lock(&watchdog_data_mutex); - kref_put(&data->kref, fschmd_release_resources); - mutex_unlock(&watchdog_data_mutex); - - return 0; -} - -static struct fschmd_data *fschmd_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct fschmd_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - - for (i = 0; i < FSCHMD_NO_TEMP_SENSORS[data->kind]; i++) { - data->temp_act[i] = i2c_smbus_read_byte_data(client, - FSCHMD_REG_TEMP_ACT[data->kind][i]); - data->temp_status[i] = i2c_smbus_read_byte_data(client, - FSCHMD_REG_TEMP_STATE[data->kind][i]); - - /* The fscpos doesn't have TEMP_LIMIT registers */ - if (FSCHMD_REG_TEMP_LIMIT[data->kind][i]) - data->temp_max[i] = i2c_smbus_read_byte_data( - client, - FSCHMD_REG_TEMP_LIMIT[data->kind][i]); - - /* - * reset alarm if the alarm condition is gone, - * the chip doesn't do this itself - */ - if ((data->temp_status[i] & FSCHMD_TEMP_ALARM_MASK) == - FSCHMD_TEMP_ALARM_MASK && - data->temp_act[i] < data->temp_max[i]) - i2c_smbus_write_byte_data(client, - FSCHMD_REG_TEMP_STATE[data->kind][i], - data->temp_status[i]); - } - - for (i = 0; i < FSCHMD_NO_FAN_SENSORS[data->kind]; i++) { - data->fan_act[i] = i2c_smbus_read_byte_data(client, - FSCHMD_REG_FAN_ACT[data->kind][i]); - data->fan_status[i] = i2c_smbus_read_byte_data(client, - FSCHMD_REG_FAN_STATE[data->kind][i]); - data->fan_ripple[i] = i2c_smbus_read_byte_data(client, - FSCHMD_REG_FAN_RIPPLE[data->kind][i]); - - /* The fscpos third fan doesn't have a fan_min */ - if (FSCHMD_REG_FAN_MIN[data->kind][i]) - data->fan_min[i] = i2c_smbus_read_byte_data( - client, - FSCHMD_REG_FAN_MIN[data->kind][i]); - - /* reset fan status if speed is back to > 0 */ - if ((data->fan_status[i] & FSCHMD_FAN_ALARM) && - data->fan_act[i]) - i2c_smbus_write_byte_data(client, - FSCHMD_REG_FAN_STATE[data->kind][i], - data->fan_status[i]); - } - - for (i = 0; i < FSCHMD_NO_VOLT_SENSORS[data->kind]; i++) - data->volt[i] = i2c_smbus_read_byte_data(client, - FSCHMD_REG_VOLT[data->kind][i]); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(fschmd_driver); - -MODULE_AUTHOR("Hans de Goede "); -MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles, Heimdall, Hades " - "and Syleus driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/g760a.c b/ANDROID_3.4.5/drivers/hwmon/g760a.c deleted file mode 100644 index ebcd2698..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/g760a.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * g760a - Driver for the Global Mixed-mode Technology Inc. G760A - * fan speed PWM controller chip - * - * Copyright (C) 2007 Herbert Valerio Riedel - * - * Complete datasheet is available at GMT's website: - * http://www.gmt.com.tw/product/datasheet/EDS-760A.pdf - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const struct i2c_device_id g760a_id[] = { - { "g760a", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, g760a_id); - -enum g760a_regs { - G760A_REG_SET_CNT = 0x00, - G760A_REG_ACT_CNT = 0x01, - G760A_REG_FAN_STA = 0x02 -}; - -#define G760A_REG_FAN_STA_RPM_OFF 0x1 /* +/-20% off */ -#define G760A_REG_FAN_STA_RPM_LOW 0x2 /* below 1920rpm */ - -/* register data is read (and cached) at most once per second */ -#define G760A_UPDATE_INTERVAL (HZ) - -struct g760a_data { - struct i2c_client *client; - struct device *hwmon_dev; - struct mutex update_lock; - - /* board specific parameters */ - u32 clk; /* default 32kHz */ - u16 fan_div; /* default P=2 */ - - /* g760a register cache */ - unsigned int valid:1; - unsigned long last_updated; /* In jiffies */ - - u8 set_cnt; /* PWM (period) count number; 0xff stops fan */ - u8 act_cnt; /* formula: cnt = (CLK * 30)/(rpm * P) */ - u8 fan_sta; /* bit 0: set when actual fan speed more than 20% - * outside requested fan speed - * bit 1: set when fan speed below 1920 rpm - */ -}; - -#define G760A_DEFAULT_CLK 32768 -#define G760A_DEFAULT_FAN_DIV 2 - -#define PWM_FROM_CNT(cnt) (0xff-(cnt)) -#define PWM_TO_CNT(pwm) (0xff-(pwm)) - -static inline unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div) -{ - return ((val == 0x00) ? 0 : ((clk*30)/(val*div))); -} - -/* new-style driver model */ -static int g760a_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int g760a_remove(struct i2c_client *client); - -static struct i2c_driver g760a_driver = { - .driver = { - .name = "g760a", - }, - .probe = g760a_probe, - .remove = g760a_remove, - .id_table = g760a_id, -}; - -/* read/write wrappers */ -static int g760a_read_value(struct i2c_client *client, enum g760a_regs reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int g760a_write_value(struct i2c_client *client, enum g760a_regs reg, - u16 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -/* - * sysfs attributes - */ - -static struct g760a_data *g760a_update_client(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct g760a_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + G760A_UPDATE_INTERVAL) - || !data->valid) { - dev_dbg(&client->dev, "Starting g760a update\n"); - - data->set_cnt = g760a_read_value(client, G760A_REG_SET_CNT); - data->act_cnt = g760a_read_value(client, G760A_REG_ACT_CNT); - data->fan_sta = g760a_read_value(client, G760A_REG_FAN_STA); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct g760a_data *data = g760a_update_client(dev); - unsigned int rpm = 0; - - mutex_lock(&data->update_lock); - if (!(data->fan_sta & G760A_REG_FAN_STA_RPM_LOW)) - rpm = rpm_from_cnt(data->act_cnt, data->clk, data->fan_div); - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct g760a_data *data = g760a_update_client(dev); - - int fan_alarm = (data->fan_sta & G760A_REG_FAN_STA_RPM_OFF) ? 1 : 0; - - return sprintf(buf, "%d\n", fan_alarm); -} - -static ssize_t get_pwm(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct g760a_data *data = g760a_update_client(dev); - - return sprintf(buf, "%d\n", PWM_FROM_CNT(data->set_cnt)); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct g760a_data *data = g760a_update_client(dev); - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->set_cnt = PWM_TO_CNT(SENSORS_LIMIT(val, 0, 255)); - g760a_write_value(client, G760A_REG_SET_CNT, data->set_cnt); - mutex_unlock(&data->update_lock); - - return count; -} - -static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); -static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL); -static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL); - -static struct attribute *g760a_attributes[] = { - &dev_attr_pwm1.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan1_alarm.attr, - NULL -}; - -static const struct attribute_group g760a_group = { - .attrs = g760a_attributes, -}; - -/* - * new-style driver model code - */ - -static int g760a_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct g760a_data *data; - int err; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - data = kzalloc(sizeof(struct g760a_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - - data->client = client; - mutex_init(&data->update_lock); - - /* setup default configuration for now */ - data->fan_div = G760A_DEFAULT_FAN_DIV; - data->clk = G760A_DEFAULT_CLK; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &g760a_group); - if (err) - goto error_sysfs_create_group; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_hwmon_device_register; - } - - return 0; - -error_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, &g760a_group); -error_sysfs_create_group: - kfree(data); - - return err; -} - -static int g760a_remove(struct i2c_client *client) -{ - struct g760a_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &g760a_group); - kfree(data); - - return 0; -} - -module_i2c_driver(g760a_driver); - -MODULE_AUTHOR("Herbert Valerio Riedel "); -MODULE_DESCRIPTION("GMT G760A driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/gl518sm.c b/ANDROID_3.4.5/drivers/hwmon/gl518sm.c deleted file mode 100644 index 764a083a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/gl518sm.c +++ /dev/null @@ -1,723 +0,0 @@ -/* - * gl518sm.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 1998, 1999 Frodo Looijaard and - * Kyosti Malkki - * Copyright (C) 2004 Hong-Gunn Chew and - * Jean Delvare - * - * 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. - * - * Ported to Linux 2.6 by Hong-Gunn Chew with the help of Jean Delvare - * and advice of Greg Kroah-Hartman. - * - * Notes about the port: - * Release 0x00 of the GL518SM chipset doesn't support reading of in0, - * in1 nor in2. The original driver had an ugly workaround to get them - * anyway (changing limits and watching alarms trigger and wear off). - * We did not keep that part of the original driver in the Linux 2.6 - * version, since it was making the driver significantly more complex - * with no real benefit. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; - -enum chips { gl518sm_r00, gl518sm_r80 }; - -/* Many GL518 constants specified below */ - -/* The GL518 registers */ -#define GL518_REG_CHIP_ID 0x00 -#define GL518_REG_REVISION 0x01 -#define GL518_REG_VENDOR_ID 0x02 -#define GL518_REG_CONF 0x03 -#define GL518_REG_TEMP_IN 0x04 -#define GL518_REG_TEMP_MAX 0x05 -#define GL518_REG_TEMP_HYST 0x06 -#define GL518_REG_FAN_COUNT 0x07 -#define GL518_REG_FAN_LIMIT 0x08 -#define GL518_REG_VIN1_LIMIT 0x09 -#define GL518_REG_VIN2_LIMIT 0x0a -#define GL518_REG_VIN3_LIMIT 0x0b -#define GL518_REG_VDD_LIMIT 0x0c -#define GL518_REG_VIN3 0x0d -#define GL518_REG_MISC 0x0f -#define GL518_REG_ALARM 0x10 -#define GL518_REG_MASK 0x11 -#define GL518_REG_INT 0x12 -#define GL518_REG_VIN2 0x13 -#define GL518_REG_VIN1 0x14 -#define GL518_REG_VDD 0x15 - - -/* - * Conversions. Rounding and limit checking is only done on the TO_REG - * variants. Note that you should be a bit careful with which arguments - * these macros are called: arguments may be evaluated more than once. - * Fixing this is just not worth it. - */ - -#define RAW_FROM_REG(val) val - -#define BOOL_FROM_REG(val) ((val) ? 0 : 1) -#define BOOL_TO_REG(val) ((val) ? 0 : 1) - -#define TEMP_TO_REG(val) SENSORS_LIMIT(((((val) < 0 ? \ - (val) - 500 : \ - (val) + 500) / 1000) + 119), 0, 255) -#define TEMP_FROM_REG(val) (((val) - 119) * 1000) - -static inline u8 FAN_TO_REG(long rpm, int div) -{ - long rpmdiv; - if (rpm == 0) - return 0; - rpmdiv = SENSORS_LIMIT(rpm, 1, 960000) * div; - return SENSORS_LIMIT((480000 + rpmdiv / 2) / rpmdiv, 1, 255); -} -#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) * (div)))) - -#define IN_TO_REG(val) SENSORS_LIMIT((((val) + 9) / 19), 0, 255) -#define IN_FROM_REG(val) ((val) * 19) - -#define VDD_TO_REG(val) SENSORS_LIMIT((((val) * 4 + 47) / 95), 0, 255) -#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4) - -#define DIV_FROM_REG(val) (1 << (val)) - -#define BEEP_MASK_TO_REG(val) ((val) & 0x7f & data->alarm_mask) -#define BEEP_MASK_FROM_REG(val) ((val) & 0x7f) - -/* Each client has this additional data */ -struct gl518_data { - struct device *hwmon_dev; - enum chips type; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 voltage_in[4]; /* Register values; [0] = VDD */ - u8 voltage_min[4]; /* Register values; [0] = VDD */ - u8 voltage_max[4]; /* Register values; [0] = VDD */ - u8 fan_in[2]; - u8 fan_min[2]; - u8 fan_div[2]; /* Register encoding, shifted right */ - u8 fan_auto1; /* Boolean */ - u8 temp_in; /* Register values */ - u8 temp_max; /* Register values */ - u8 temp_hyst; /* Register values */ - u8 alarms; /* Register value */ - u8 alarm_mask; - u8 beep_mask; /* Register value */ - u8 beep_enable; /* Boolean */ -}; - -static int gl518_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info); -static void gl518_init_client(struct i2c_client *client); -static int gl518_remove(struct i2c_client *client); -static int gl518_read_value(struct i2c_client *client, u8 reg); -static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); -static struct gl518_data *gl518_update_device(struct device *dev); - -static const struct i2c_device_id gl518_id[] = { - { "gl518sm", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl518_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver gl518_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "gl518sm", - }, - .probe = gl518_probe, - .remove = gl518_remove, - .id_table = gl518_id, - .detect = gl518_detect, - .address_list = normal_i2c, -}; - -/* - * Sysfs stuff - */ - -#define show(type, suffix, value) \ -static ssize_t show_##suffix(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct gl518_data *data = gl518_update_device(dev); \ - return sprintf(buf, "%d\n", type##_FROM_REG(data->value)); \ -} - -show(TEMP, temp_input1, temp_in); -show(TEMP, temp_max1, temp_max); -show(TEMP, temp_hyst1, temp_hyst); -show(BOOL, fan_auto1, fan_auto1); -show(VDD, in_input0, voltage_in[0]); -show(IN, in_input1, voltage_in[1]); -show(IN, in_input2, voltage_in[2]); -show(IN, in_input3, voltage_in[3]); -show(VDD, in_min0, voltage_min[0]); -show(IN, in_min1, voltage_min[1]); -show(IN, in_min2, voltage_min[2]); -show(IN, in_min3, voltage_min[3]); -show(VDD, in_max0, voltage_max[0]); -show(IN, in_max1, voltage_max[1]); -show(IN, in_max2, voltage_max[2]); -show(IN, in_max3, voltage_max[3]); -show(RAW, alarms, alarms); -show(BOOL, beep_enable, beep_enable); -show(BEEP_MASK, beep_mask, beep_mask); - -static ssize_t show_fan_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct gl518_data *data = gl518_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_in[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct gl518_data *data = gl518_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct gl518_data *data = gl518_update_device(dev); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} - -#define set(type, suffix, value, reg) \ -static ssize_t set_##suffix(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct gl518_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ - \ - mutex_lock(&data->update_lock); \ - data->value = type##_TO_REG(val); \ - gl518_write_value(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -#define set_bits(type, suffix, value, reg, mask, shift) \ -static ssize_t set_##suffix(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct gl518_data *data = i2c_get_clientdata(client); \ - int regvalue; \ - unsigned long val; \ - int err = kstrtoul(buf, 10, &val); \ - if (err) \ - return err; \ - \ - mutex_lock(&data->update_lock); \ - regvalue = gl518_read_value(client, reg); \ - data->value = type##_TO_REG(val); \ - regvalue = (regvalue & ~mask) | (data->value << shift); \ - gl518_write_value(client, reg, regvalue); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -#define set_low(type, suffix, value, reg) \ - set_bits(type, suffix, value, reg, 0x00ff, 0) -#define set_high(type, suffix, value, reg) \ - set_bits(type, suffix, value, reg, 0xff00, 8) - -set(TEMP, temp_max1, temp_max, GL518_REG_TEMP_MAX); -set(TEMP, temp_hyst1, temp_hyst, GL518_REG_TEMP_HYST); -set_bits(BOOL, fan_auto1, fan_auto1, GL518_REG_MISC, 0x08, 3); -set_low(VDD, in_min0, voltage_min[0], GL518_REG_VDD_LIMIT); -set_low(IN, in_min1, voltage_min[1], GL518_REG_VIN1_LIMIT); -set_low(IN, in_min2, voltage_min[2], GL518_REG_VIN2_LIMIT); -set_low(IN, in_min3, voltage_min[3], GL518_REG_VIN3_LIMIT); -set_high(VDD, in_max0, voltage_max[0], GL518_REG_VDD_LIMIT); -set_high(IN, in_max1, voltage_max[1], GL518_REG_VIN1_LIMIT); -set_high(IN, in_max2, voltage_max[2], GL518_REG_VIN2_LIMIT); -set_high(IN, in_max3, voltage_max[3], GL518_REG_VIN3_LIMIT); -set_bits(BOOL, beep_enable, beep_enable, GL518_REG_CONF, 0x04, 2); -set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM); - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - int regvalue; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - regvalue = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - regvalue = (regvalue & (0xff << (8 * nr))) - | (data->fan_min[nr] << (8 * (1 - nr))); - gl518_write_value(client, GL518_REG_FAN_LIMIT, regvalue); - - data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); - if (data->fan_min[nr] == 0) - data->alarm_mask &= ~(0x20 << nr); - else - data->alarm_mask |= (0x20 << nr); - data->beep_mask &= data->alarm_mask; - gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - int regvalue; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - switch (val) { - case 1: - val = 0; - break; - case 2: - val = 1; - break; - case 4: - val = 2; - break; - case 8: - val = 3; - break; - default: - dev_err(dev, "Invalid fan clock divider %lu, choose one " - "of 1, 2, 4 or 8\n", val); - return -EINVAL; - } - - mutex_lock(&data->update_lock); - regvalue = gl518_read_value(client, GL518_REG_MISC); - data->fan_div[nr] = val; - regvalue = (regvalue & ~(0xc0 >> (2 * nr))) - | (data->fan_div[nr] << (6 - 2 * nr)); - gl518_write_value(client, GL518_REG_MISC, regvalue); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); -static DEVICE_ATTR(temp1_max, S_IWUSR|S_IRUGO, show_temp_max1, set_temp_max1); -static DEVICE_ATTR(temp1_max_hyst, S_IWUSR|S_IRUGO, - show_temp_hyst1, set_temp_hyst1); -static DEVICE_ATTR(fan1_auto, S_IWUSR|S_IRUGO, show_fan_auto1, set_fan_auto1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR|S_IRUGO, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR|S_IRUGO, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR|S_IRUGO, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR|S_IRUGO, - show_fan_div, set_fan_div, 1); -static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input0, NULL); -static DEVICE_ATTR(in1_input, S_IRUGO, show_in_input1, NULL); -static DEVICE_ATTR(in2_input, S_IRUGO, show_in_input2, NULL); -static DEVICE_ATTR(in3_input, S_IRUGO, show_in_input3, NULL); -static DEVICE_ATTR(in0_min, S_IWUSR|S_IRUGO, show_in_min0, set_in_min0); -static DEVICE_ATTR(in1_min, S_IWUSR|S_IRUGO, show_in_min1, set_in_min1); -static DEVICE_ATTR(in2_min, S_IWUSR|S_IRUGO, show_in_min2, set_in_min2); -static DEVICE_ATTR(in3_min, S_IWUSR|S_IRUGO, show_in_min3, set_in_min3); -static DEVICE_ATTR(in0_max, S_IWUSR|S_IRUGO, show_in_max0, set_in_max0); -static DEVICE_ATTR(in1_max, S_IWUSR|S_IRUGO, show_in_max1, set_in_max1); -static DEVICE_ATTR(in2_max, S_IWUSR|S_IRUGO, show_in_max2, set_in_max2); -static DEVICE_ATTR(in3_max, S_IWUSR|S_IRUGO, show_in_max3, set_in_max3); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static DEVICE_ATTR(beep_enable, S_IWUSR|S_IRUGO, - show_beep_enable, set_beep_enable); -static DEVICE_ATTR(beep_mask, S_IWUSR|S_IRUGO, - show_beep_mask, set_beep_mask); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct gl518_data *data = gl518_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -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(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6); - -static ssize_t show_beep(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct gl518_data *data = gl518_update_device(dev); - return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); -} - -static ssize_t set_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); - int bitnr = to_sensor_dev_attr(attr)->index; - unsigned long bit; - int err; - - err = kstrtoul(buf, 10, &bit); - if (err) - return err; - - if (bit & ~1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); - if (bit) - data->beep_mask |= (1 << bitnr); - else - data->beep_mask &= ~(1 << bitnr); - gl518_write_value(client, GL518_REG_ALARM, data->beep_mask); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 2); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 3); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 4); -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 5); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO|S_IWUSR, show_beep, set_beep, 6); - -static struct attribute *gl518_attributes[] = { - &dev_attr_in3_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in1_min.attr, - &dev_attr_in2_min.attr, - &dev_attr_in3_min.attr, - &dev_attr_in0_max.attr, - &dev_attr_in1_max.attr, - &dev_attr_in2_max.attr, - &dev_attr_in3_max.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in0_beep.dev_attr.attr, - &sensor_dev_attr_in1_beep.dev_attr.attr, - &sensor_dev_attr_in2_beep.dev_attr.attr, - &sensor_dev_attr_in3_beep.dev_attr.attr, - - &dev_attr_fan1_auto.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_beep.dev_attr.attr, - &sensor_dev_attr_fan2_beep.dev_attr.attr, - - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_beep.dev_attr.attr, - - &dev_attr_alarms.attr, - &dev_attr_beep_enable.attr, - &dev_attr_beep_mask.attr, - NULL -}; - -static const struct attribute_group gl518_group = { - .attrs = gl518_attributes, -}; - -static struct attribute *gl518_attributes_r80[] = { - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - &dev_attr_in2_input.attr, - NULL -}; - -static const struct attribute_group gl518_group_r80 = { - .attrs = gl518_attributes_r80, -}; - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int rev; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - /* Now, we do the remaining detection. */ - if ((gl518_read_value(client, GL518_REG_CHIP_ID) != 0x80) - || (gl518_read_value(client, GL518_REG_CONF) & 0x80)) - return -ENODEV; - - /* Determine the chip type. */ - rev = gl518_read_value(client, GL518_REG_REVISION); - if (rev != 0x00 && rev != 0x80) - return -ENODEV; - - strlcpy(info->type, "gl518sm", I2C_NAME_SIZE); - - return 0; -} - -static int gl518_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl518_data *data; - int err, revision; - - data = kzalloc(sizeof(struct gl518_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - revision = gl518_read_value(client, GL518_REG_REVISION); - data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00; - mutex_init(&data->update_lock); - - /* Initialize the GL518SM chip */ - data->alarm_mask = 0xff; - gl518_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &gl518_group); - if (err) - goto exit_free; - if (data->type == gl518sm_r80) { - err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &gl518_group); - if (data->type == gl518sm_r80) - sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); -exit_free: - kfree(data); -exit: - return err; -} - - -/* - * Called when we have found a new GL518SM. - * Note that we preserve D4:NoFan2 and D2:beep_enable. - */ -static void gl518_init_client(struct i2c_client *client) -{ - /* Make sure we leave D7:Reset untouched */ - u8 regvalue = gl518_read_value(client, GL518_REG_CONF) & 0x7f; - - /* Comparator mode (D3=0), standby mode (D6=0) */ - gl518_write_value(client, GL518_REG_CONF, (regvalue &= 0x37)); - - /* Never interrupts */ - gl518_write_value(client, GL518_REG_MASK, 0x00); - - /* Clear status register (D5=1), start (D6=1) */ - gl518_write_value(client, GL518_REG_CONF, 0x20 | regvalue); - gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue); -} - -static int gl518_remove(struct i2c_client *client) -{ - struct gl518_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &gl518_group); - if (data->type == gl518sm_r80) - sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); - - kfree(data); - return 0; -} - -/* - * Registers 0x07 to 0x0c are word-sized, others are byte-sized - * GL518 uses a high-byte first convention, which is exactly opposite to - * the SMBus standard. - */ -static int gl518_read_value(struct i2c_client *client, u8 reg) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_read_word_swapped(client, reg); - else - return i2c_smbus_read_byte_data(client, reg); -} - -static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_write_word_swapped(client, reg, value); - else - return i2c_smbus_write_byte_data(client, reg, value); -} - -static struct gl518_data *gl518_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); - int val; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - dev_dbg(&client->dev, "Starting gl518 update\n"); - - data->alarms = gl518_read_value(client, GL518_REG_INT); - data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); - - val = gl518_read_value(client, GL518_REG_VDD_LIMIT); - data->voltage_min[0] = val & 0xff; - data->voltage_max[0] = (val >> 8) & 0xff; - val = gl518_read_value(client, GL518_REG_VIN1_LIMIT); - data->voltage_min[1] = val & 0xff; - data->voltage_max[1] = (val >> 8) & 0xff; - val = gl518_read_value(client, GL518_REG_VIN2_LIMIT); - data->voltage_min[2] = val & 0xff; - data->voltage_max[2] = (val >> 8) & 0xff; - val = gl518_read_value(client, GL518_REG_VIN3_LIMIT); - data->voltage_min[3] = val & 0xff; - data->voltage_max[3] = (val >> 8) & 0xff; - - val = gl518_read_value(client, GL518_REG_FAN_COUNT); - data->fan_in[0] = (val >> 8) & 0xff; - data->fan_in[1] = val & 0xff; - - val = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[0] = (val >> 8) & 0xff; - data->fan_min[1] = val & 0xff; - - data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN); - data->temp_max = - gl518_read_value(client, GL518_REG_TEMP_MAX); - data->temp_hyst = - gl518_read_value(client, GL518_REG_TEMP_HYST); - - val = gl518_read_value(client, GL518_REG_MISC); - data->fan_div[0] = (val >> 6) & 0x03; - data->fan_div[1] = (val >> 4) & 0x03; - data->fan_auto1 = (val >> 3) & 0x01; - - data->alarms &= data->alarm_mask; - - val = gl518_read_value(client, GL518_REG_CONF); - data->beep_enable = (val >> 2) & 1; - - if (data->type != gl518sm_r00) { - data->voltage_in[0] = - gl518_read_value(client, GL518_REG_VDD); - data->voltage_in[1] = - gl518_read_value(client, GL518_REG_VIN1); - data->voltage_in[2] = - gl518_read_value(client, GL518_REG_VIN2); - } - data->voltage_in[3] = - gl518_read_value(client, GL518_REG_VIN3); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(gl518_driver); - -MODULE_AUTHOR("Frodo Looijaard , " - "Kyosti Malkki and " - "Hong-Gunn Chew "); -MODULE_DESCRIPTION("GL518SM driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/gl520sm.c b/ANDROID_3.4.5/drivers/hwmon/gl520sm.c deleted file mode 100644 index 5ff452b6..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/gl520sm.c +++ /dev/null @@ -1,981 +0,0 @@ -/* - * gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998, 1999 Frodo Looijaard , - * Kyösti Mälkki - * Copyright (c) 2005 Maarten Deprez - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Type of the extra sensor */ -static unsigned short extra_sensor_type; -module_param(extra_sensor_type, ushort, 0); -MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=temperature, 2=voltage)"); - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; - -/* - * Many GL520 constants specified below - * One of the inputs can be configured as either temp or voltage. - * That's why _TEMP2 and _IN4 access the same register - */ - -/* The GL520 registers */ -#define GL520_REG_CHIP_ID 0x00 -#define GL520_REG_REVISION 0x01 -#define GL520_REG_CONF 0x03 -#define GL520_REG_MASK 0x11 - -#define GL520_REG_VID_INPUT 0x02 - -static const u8 GL520_REG_IN_INPUT[] = { 0x15, 0x14, 0x13, 0x0d, 0x0e }; -static const u8 GL520_REG_IN_LIMIT[] = { 0x0c, 0x09, 0x0a, 0x0b }; -static const u8 GL520_REG_IN_MIN[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x18 }; -static const u8 GL520_REG_IN_MAX[] = { 0x0c, 0x09, 0x0a, 0x0b, 0x17 }; - -static const u8 GL520_REG_TEMP_INPUT[] = { 0x04, 0x0e }; -static const u8 GL520_REG_TEMP_MAX[] = { 0x05, 0x17 }; -static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; - -#define GL520_REG_FAN_INPUT 0x07 -#define GL520_REG_FAN_MIN 0x08 -#define GL520_REG_FAN_DIV 0x0f -#define GL520_REG_FAN_OFF GL520_REG_FAN_DIV - -#define GL520_REG_ALARMS 0x12 -#define GL520_REG_BEEP_MASK 0x10 -#define GL520_REG_BEEP_ENABLE GL520_REG_CONF - -/* - * Function declarations - */ - -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info); -static void gl520_init_client(struct i2c_client *client); -static int gl520_remove(struct i2c_client *client); -static int gl520_read_value(struct i2c_client *client, u8 reg); -static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value); -static struct gl520_data *gl520_update_device(struct device *dev); - -/* Driver data */ -static const struct i2c_device_id gl520_id[] = { - { "gl520sm", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl520_id); - -static struct i2c_driver gl520_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "gl520sm", - }, - .probe = gl520_probe, - .remove = gl520_remove, - .id_table = gl520_id, - .detect = gl520_detect, - .address_list = normal_i2c, -}; - -/* Client data */ -struct gl520_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until the following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - u8 vid; - u8 vrm; - u8 in_input[5]; /* [0] = VVD */ - u8 in_min[5]; /* [0] = VDD */ - u8 in_max[5]; /* [0] = VDD */ - u8 fan_input[2]; - u8 fan_min[2]; - u8 fan_div[2]; - u8 fan_off; - u8 temp_input[2]; - u8 temp_max[2]; - u8 temp_max_hyst[2]; - u8 alarms; - u8 beep_enable; - u8 beep_mask; - u8 alarm_mask; - u8 two_temps; -}; - -/* - * Sysfs stuff - */ - -static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gl520_data *data = gl520_update_device(dev); - return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, get_cpu_vid, NULL); - -#define VDD_FROM_REG(val) (((val) * 95 + 2) / 4) -#define VDD_TO_REG(val) SENSORS_LIMIT((((val) * 4 + 47) / 95), 0, 255) - -#define IN_FROM_REG(val) ((val) * 19) -#define IN_TO_REG(val) SENSORS_LIMIT((((val) + 9) / 19), 0, 255) - -static ssize_t get_in_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - u8 r = data->in_input[n]; - - if (n == 0) - return sprintf(buf, "%d\n", VDD_FROM_REG(r)); - else - return sprintf(buf, "%d\n", IN_FROM_REG(r)); -} - -static ssize_t get_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - u8 r = data->in_min[n]; - - if (n == 0) - return sprintf(buf, "%d\n", VDD_FROM_REG(r)); - else - return sprintf(buf, "%d\n", IN_FROM_REG(r)); -} - -static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - u8 r = data->in_max[n]; - - if (n == 0) - return sprintf(buf, "%d\n", VDD_FROM_REG(r)); - else - return sprintf(buf, "%d\n", IN_FROM_REG(r)); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int n = to_sensor_dev_attr(attr)->index; - u8 r; - long v; - int err; - - err = kstrtol(buf, 10, &v); - if (err) - return err; - - mutex_lock(&data->update_lock); - - if (n == 0) - r = VDD_TO_REG(v); - else - r = IN_TO_REG(v); - - data->in_min[n] = r; - - if (n < 4) - gl520_write_value(client, GL520_REG_IN_MIN[n], - (gl520_read_value(client, GL520_REG_IN_MIN[n]) - & ~0xff) | r); - else - gl520_write_value(client, GL520_REG_IN_MIN[n], r); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int n = to_sensor_dev_attr(attr)->index; - u8 r; - long v; - int err; - - err = kstrtol(buf, 10, &v); - if (err) - return err; - - if (n == 0) - r = VDD_TO_REG(v); - else - r = IN_TO_REG(v); - - mutex_lock(&data->update_lock); - - data->in_max[n] = r; - - if (n < 4) - gl520_write_value(client, GL520_REG_IN_MAX[n], - (gl520_read_value(client, GL520_REG_IN_MAX[n]) - & ~0xff00) | (r << 8)); - else - gl520_write_value(client, GL520_REG_IN_MAX[n], r); - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, get_in_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, get_in_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, get_in_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, get_in_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, get_in_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 0); -static SENSOR_DEVICE_ATTR(in1_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 3); -static SENSOR_DEVICE_ATTR(in4_min, S_IRUGO | S_IWUSR, - get_in_min, set_in_min, 4); -static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 0); -static SENSOR_DEVICE_ATTR(in1_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 1); -static SENSOR_DEVICE_ATTR(in2_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 2); -static SENSOR_DEVICE_ATTR(in3_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 3); -static SENSOR_DEVICE_ATTR(in4_max, S_IRUGO | S_IWUSR, - get_in_max, set_in_max, 4); - -#define DIV_FROM_REG(val) (1 << (val)) -#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (480000 / ((val) << (div)))) -#define FAN_TO_REG(val, div) ((val) <= 0 ? 0 : \ - SENSORS_LIMIT((480000 + ((val) << ((div)-1))) / ((val) << (div)), 1, \ - 255)) - -static ssize_t get_fan_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_input[n], - data->fan_div[n])); -} - -static ssize_t get_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[n], - data->fan_div[n])); -} - -static ssize_t get_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[n])); -} - -static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gl520_data *data = gl520_update_device(dev); - return sprintf(buf, "%d\n", data->fan_off); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int n = to_sensor_dev_attr(attr)->index; - u8 r; - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - mutex_lock(&data->update_lock); - r = FAN_TO_REG(v, data->fan_div[n]); - data->fan_min[n] = r; - - if (n == 0) - gl520_write_value(client, GL520_REG_FAN_MIN, - (gl520_read_value(client, GL520_REG_FAN_MIN) - & ~0xff00) | (r << 8)); - else - gl520_write_value(client, GL520_REG_FAN_MIN, - (gl520_read_value(client, GL520_REG_FAN_MIN) - & ~0xff) | r); - - data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - if (data->fan_min[n] == 0) - data->alarm_mask &= (n == 0) ? ~0x20 : ~0x40; - else - data->alarm_mask |= (n == 0) ? 0x20 : 0x40; - data->beep_mask &= data->alarm_mask; - gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int n = to_sensor_dev_attr(attr)->index; - u8 r; - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - switch (v) { - case 1: - r = 0; - break; - case 2: - r = 1; - break; - case 4: - r = 2; - break; - case 8: - r = 3; - break; - default: - dev_err(&client->dev, - "fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v); - return -EINVAL; - } - - mutex_lock(&data->update_lock); - data->fan_div[n] = r; - - if (n == 0) - gl520_write_value(client, GL520_REG_FAN_DIV, - (gl520_read_value(client, GL520_REG_FAN_DIV) - & ~0xc0) | (r << 6)); - else - gl520_write_value(client, GL520_REG_FAN_DIV, - (gl520_read_value(client, GL520_REG_FAN_DIV) - & ~0x30) | (r << 4)); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - u8 r; - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - r = (v ? 1 : 0); - - mutex_lock(&data->update_lock); - data->fan_off = r; - gl520_write_value(client, GL520_REG_FAN_OFF, - (gl520_read_value(client, GL520_REG_FAN_OFF) - & ~0x0c) | (r << 2)); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, - get_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, - get_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - get_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - get_fan_div, set_fan_div, 1); -static DEVICE_ATTR(fan1_off, S_IRUGO | S_IWUSR, - get_fan_off, set_fan_off); - -#define TEMP_FROM_REG(val) (((val) - 130) * 1000) -#define TEMP_TO_REG(val) SENSORS_LIMIT(((((val) < 0 ? \ - (val) - 500 : (val) + 500) / 1000) + 130), 0, 255) - -static ssize_t get_temp_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_input[n])); -} - -static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[n])); -} - -static ssize_t get_temp_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int n = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max_hyst[n])); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int n = to_sensor_dev_attr(attr)->index; - long v; - int err; - - err = kstrtol(buf, 10, &v); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[n] = TEMP_TO_REG(v); - gl520_write_value(client, GL520_REG_TEMP_MAX[n], data->temp_max[n]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int n = to_sensor_dev_attr(attr)->index; - long v; - int err; - - err = kstrtol(buf, 10, &v); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max_hyst[n] = TEMP_TO_REG(v); - gl520_write_value(client, GL520_REG_TEMP_MAX_HYST[n], - data->temp_max_hyst[n]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, get_temp_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - get_temp_max, set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO | S_IWUSR, - get_temp_max, set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - get_temp_max_hyst, set_temp_max_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, - get_temp_max_hyst, set_temp_max_hyst, 1); - -static ssize_t get_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gl520_data *data = gl520_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} - -static ssize_t get_beep_enable(struct device *dev, struct device_attribute - *attr, char *buf) -{ - struct gl520_data *data = gl520_update_device(dev); - return sprintf(buf, "%d\n", data->beep_enable); -} - -static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct gl520_data *data = gl520_update_device(dev); - return sprintf(buf, "%d\n", data->beep_mask); -} - -static ssize_t set_beep_enable(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - u8 r; - unsigned long v; - int err; - - err = kstrtoul(buf, 10, &v); - if (err) - return err; - - r = (v ? 0 : 1); - - mutex_lock(&data->update_lock); - data->beep_enable = !r; - gl520_write_value(client, GL520_REG_BEEP_ENABLE, - (gl520_read_value(client, GL520_REG_BEEP_ENABLE) - & ~0x04) | (r << 2)); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - unsigned long r; - int err; - - err = kstrtoul(buf, 10, &r); - if (err) - return err; - - mutex_lock(&data->update_lock); - r &= data->alarm_mask; - data->beep_mask = r; - gl520_write_value(client, GL520_REG_BEEP_MASK, r); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); -static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, - get_beep_enable, set_beep_enable); -static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, - get_beep_mask, set_beep_mask); - -static ssize_t get_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bit_nr = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", (data->alarms >> bit_nr) & 1); -} - -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, get_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, get_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, get_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, get_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, get_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, get_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, get_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, get_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, get_alarm, NULL, 7); - -static ssize_t get_beep(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct gl520_data *data = gl520_update_device(dev); - - return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); -} - -static ssize_t set_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int bitnr = to_sensor_dev_attr(attr)->index; - unsigned long bit; - - int err; - - err = kstrtoul(buf, 10, &bit); - if (err) - return err; - if (bit & ~1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - if (bit) - data->beep_mask |= (1 << bitnr); - else - data->beep_mask &= ~(1 << bitnr); - gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 2); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 3); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 4); -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 5); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 6); -static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); -static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, get_beep, set_beep, 7); - -static struct attribute *gl520_attributes[] = { - &dev_attr_cpu0_vid.attr, - - &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, - &sensor_dev_attr_in0_beep.dev_attr.attr, - &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, - &sensor_dev_attr_in1_beep.dev_attr.attr, - &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, - &sensor_dev_attr_in2_beep.dev_attr.attr, - &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, - &sensor_dev_attr_in3_beep.dev_attr.attr, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_beep.dev_attr.attr, - &dev_attr_fan1_off.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_beep.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_beep.dev_attr.attr, - - &dev_attr_alarms.attr, - &dev_attr_beep_enable.attr, - &dev_attr_beep_mask.attr, - NULL -}; - -static const struct attribute_group gl520_group = { - .attrs = gl520_attributes, -}; - -static struct attribute *gl520_attributes_in4[] = { - &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, - &sensor_dev_attr_in4_beep.dev_attr.attr, - NULL -}; - -static struct attribute *gl520_attributes_temp2[] = { - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_beep.dev_attr.attr, - NULL -}; - -static const struct attribute_group gl520_group_in4 = { - .attrs = gl520_attributes_in4, -}; - -static const struct attribute_group gl520_group_temp2 = { - .attrs = gl520_attributes_temp2, -}; - - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - /* Determine the chip type. */ - if ((gl520_read_value(client, GL520_REG_CHIP_ID) != 0x20) || - ((gl520_read_value(client, GL520_REG_REVISION) & 0x7f) != 0x00) || - ((gl520_read_value(client, GL520_REG_CONF) & 0x80) != 0x00)) { - dev_dbg(&client->dev, "Unknown chip type, skipping\n"); - return -ENODEV; - } - - strlcpy(info->type, "gl520sm", I2C_NAME_SIZE); - - return 0; -} - -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl520_data *data; - int err; - - data = kzalloc(sizeof(struct gl520_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the GL520SM chip */ - gl520_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &gl520_group); - if (err) - goto exit_free; - - if (data->two_temps) - err = sysfs_create_group(&client->dev.kobj, &gl520_group_temp2); - else - err = sysfs_create_group(&client->dev.kobj, &gl520_group_in4); - - if (err) - goto exit_remove_files; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &gl520_group); - sysfs_remove_group(&client->dev.kobj, &gl520_group_in4); - sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2); -exit_free: - kfree(data); -exit: - return err; -} - - -/* Called when we have found a new GL520SM. */ -static void gl520_init_client(struct i2c_client *client) -{ - struct gl520_data *data = i2c_get_clientdata(client); - u8 oldconf, conf; - - conf = oldconf = gl520_read_value(client, GL520_REG_CONF); - - data->alarm_mask = 0xff; - data->vrm = vid_which_vrm(); - - if (extra_sensor_type == 1) - conf &= ~0x10; - else if (extra_sensor_type == 2) - conf |= 0x10; - data->two_temps = !(conf & 0x10); - - /* If IRQ# is disabled, we can safely force comparator mode */ - if (!(conf & 0x20)) - conf &= 0xf7; - - /* Enable monitoring if needed */ - conf |= 0x40; - - if (conf != oldconf) - gl520_write_value(client, GL520_REG_CONF, conf); - - gl520_update_device(&(client->dev)); - - if (data->fan_min[0] == 0) - data->alarm_mask &= ~0x20; - if (data->fan_min[1] == 0) - data->alarm_mask &= ~0x40; - - data->beep_mask &= data->alarm_mask; - gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); -} - -static int gl520_remove(struct i2c_client *client) -{ - struct gl520_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &gl520_group); - sysfs_remove_group(&client->dev.kobj, &gl520_group_in4); - sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2); - - kfree(data); - return 0; -} - - -/* - * Registers 0x07 to 0x0c are word-sized, others are byte-sized - * GL520 uses a high-byte first convention - */ -static int gl520_read_value(struct i2c_client *client, u8 reg) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_read_word_swapped(client, reg); - else - return i2c_smbus_read_byte_data(client, reg); -} - -static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_write_word_swapped(client, reg, value); - else - return i2c_smbus_write_byte_data(client, reg, value); -} - - -static struct gl520_data *gl520_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int val, i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - - dev_dbg(&client->dev, "Starting gl520sm update\n"); - - data->alarms = gl520_read_value(client, GL520_REG_ALARMS); - data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - data->vid = gl520_read_value(client, - GL520_REG_VID_INPUT) & 0x1f; - - for (i = 0; i < 4; i++) { - data->in_input[i] = gl520_read_value(client, - GL520_REG_IN_INPUT[i]); - val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); - data->in_min[i] = val & 0xff; - data->in_max[i] = (val >> 8) & 0xff; - } - - val = gl520_read_value(client, GL520_REG_FAN_INPUT); - data->fan_input[0] = (val >> 8) & 0xff; - data->fan_input[1] = val & 0xff; - - val = gl520_read_value(client, GL520_REG_FAN_MIN); - data->fan_min[0] = (val >> 8) & 0xff; - data->fan_min[1] = val & 0xff; - - data->temp_input[0] = gl520_read_value(client, - GL520_REG_TEMP_INPUT[0]); - data->temp_max[0] = gl520_read_value(client, - GL520_REG_TEMP_MAX[0]); - data->temp_max_hyst[0] = gl520_read_value(client, - GL520_REG_TEMP_MAX_HYST[0]); - - val = gl520_read_value(client, GL520_REG_FAN_DIV); - data->fan_div[0] = (val >> 6) & 0x03; - data->fan_div[1] = (val >> 4) & 0x03; - data->fan_off = (val >> 2) & 0x01; - - data->alarms &= data->alarm_mask; - - val = gl520_read_value(client, GL520_REG_CONF); - data->beep_enable = !((val >> 2) & 1); - - /* Temp1 and Vin4 are the same input */ - if (data->two_temps) { - data->temp_input[1] = gl520_read_value(client, - GL520_REG_TEMP_INPUT[1]); - data->temp_max[1] = gl520_read_value(client, - GL520_REG_TEMP_MAX[1]); - data->temp_max_hyst[1] = gl520_read_value(client, - GL520_REG_TEMP_MAX_HYST[1]); - } else { - data->in_input[4] = gl520_read_value(client, - GL520_REG_IN_INPUT[4]); - data->in_min[4] = gl520_read_value(client, - GL520_REG_IN_MIN[4]); - data->in_max[4] = gl520_read_value(client, - GL520_REG_IN_MAX[4]); - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(gl520_driver); - -MODULE_AUTHOR("Frodo Looijaard , " - "Kyösti Mälkki , " - "Maarten Deprez "); -MODULE_DESCRIPTION("GL520SM driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/gpio-fan.c b/ANDROID_3.4.5/drivers/hwmon/gpio-fan.c deleted file mode 100644 index 2ce8c44a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/gpio-fan.c +++ /dev/null @@ -1,547 +0,0 @@ -/* - * gpio-fan.c - Hwmon driver for fans connected to GPIO lines. - * - * Copyright (C) 2010 LaCie - * - * Author: Simon Guinot - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct gpio_fan_data { - struct platform_device *pdev; - struct device *hwmon_dev; - struct mutex lock; /* lock GPIOs operations. */ - int num_ctrl; - unsigned *ctrl; - int num_speed; - struct gpio_fan_speed *speed; - int speed_index; -#ifdef CONFIG_PM - int resume_speed; -#endif - bool pwm_enable; - struct gpio_fan_alarm *alarm; - struct work_struct alarm_work; -}; - -/* - * Alarm GPIO. - */ - -static void fan_alarm_notify(struct work_struct *ws) -{ - struct gpio_fan_data *fan_data = - container_of(ws, struct gpio_fan_data, alarm_work); - - sysfs_notify(&fan_data->pdev->dev.kobj, NULL, "fan1_alarm"); - kobject_uevent(&fan_data->pdev->dev.kobj, KOBJ_CHANGE); -} - -static irqreturn_t fan_alarm_irq_handler(int irq, void *dev_id) -{ - struct gpio_fan_data *fan_data = dev_id; - - schedule_work(&fan_data->alarm_work); - - return IRQ_NONE; -} - -static ssize_t show_fan_alarm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - struct gpio_fan_alarm *alarm = fan_data->alarm; - int value = gpio_get_value(alarm->gpio); - - if (alarm->active_low) - value = !value; - - return sprintf(buf, "%d\n", value); -} - -static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL); - -static int fan_alarm_init(struct gpio_fan_data *fan_data, - struct gpio_fan_alarm *alarm) -{ - int err; - int alarm_irq; - struct platform_device *pdev = fan_data->pdev; - - fan_data->alarm = alarm; - - err = gpio_request(alarm->gpio, "GPIO fan alarm"); - if (err) - return err; - - err = gpio_direction_input(alarm->gpio); - if (err) - goto err_free_gpio; - - err = device_create_file(&pdev->dev, &dev_attr_fan1_alarm); - if (err) - goto err_free_gpio; - - /* - * If the alarm GPIO don't support interrupts, just leave - * without initializing the fail notification support. - */ - alarm_irq = gpio_to_irq(alarm->gpio); - if (alarm_irq < 0) - return 0; - - INIT_WORK(&fan_data->alarm_work, fan_alarm_notify); - irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH); - err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED, - "GPIO fan alarm", fan_data); - if (err) - goto err_free_sysfs; - - return 0; - -err_free_sysfs: - device_remove_file(&pdev->dev, &dev_attr_fan1_alarm); -err_free_gpio: - gpio_free(alarm->gpio); - - return err; -} - -static void fan_alarm_free(struct gpio_fan_data *fan_data) -{ - struct platform_device *pdev = fan_data->pdev; - int alarm_irq = gpio_to_irq(fan_data->alarm->gpio); - - if (alarm_irq >= 0) - free_irq(alarm_irq, fan_data); - device_remove_file(&pdev->dev, &dev_attr_fan1_alarm); - gpio_free(fan_data->alarm->gpio); -} - -/* - * Control GPIOs. - */ - -/* Must be called with fan_data->lock held, except during initialization. */ -static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val) -{ - int i; - - for (i = 0; i < fan_data->num_ctrl; i++) - gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1); -} - -static int __get_fan_ctrl(struct gpio_fan_data *fan_data) -{ - int i; - int ctrl_val = 0; - - for (i = 0; i < fan_data->num_ctrl; i++) { - int value; - - value = gpio_get_value(fan_data->ctrl[i]); - ctrl_val |= (value << i); - } - return ctrl_val; -} - -/* Must be called with fan_data->lock held, except during initialization. */ -static void set_fan_speed(struct gpio_fan_data *fan_data, int speed_index) -{ - if (fan_data->speed_index == speed_index) - return; - - __set_fan_ctrl(fan_data, fan_data->speed[speed_index].ctrl_val); - fan_data->speed_index = speed_index; -} - -static int get_fan_speed_index(struct gpio_fan_data *fan_data) -{ - int ctrl_val = __get_fan_ctrl(fan_data); - int i; - - for (i = 0; i < fan_data->num_speed; i++) - if (fan_data->speed[i].ctrl_val == ctrl_val) - return i; - - dev_warn(&fan_data->pdev->dev, - "missing speed array entry for GPIO value 0x%x\n", ctrl_val); - - return -EINVAL; -} - -static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm) -{ - struct gpio_fan_speed *speed = fan_data->speed; - int i; - - for (i = 0; i < fan_data->num_speed; i++) - if (speed[i].rpm >= rpm) - return i; - - return fan_data->num_speed - 1; -} - -static ssize_t show_pwm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - u8 pwm = fan_data->speed_index * 255 / (fan_data->num_speed - 1); - - return sprintf(buf, "%d\n", pwm); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - unsigned long pwm; - int speed_index; - int ret = count; - - if (kstrtoul(buf, 10, &pwm) || pwm > 255) - return -EINVAL; - - mutex_lock(&fan_data->lock); - - if (!fan_data->pwm_enable) { - ret = -EPERM; - goto exit_unlock; - } - - speed_index = DIV_ROUND_UP(pwm * (fan_data->num_speed - 1), 255); - set_fan_speed(fan_data, speed_index); - -exit_unlock: - mutex_unlock(&fan_data->lock); - - return ret; -} - -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", fan_data->pwm_enable); -} - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - unsigned long val; - - if (kstrtoul(buf, 10, &val) || val > 1) - return -EINVAL; - - if (fan_data->pwm_enable == val) - return count; - - mutex_lock(&fan_data->lock); - - fan_data->pwm_enable = val; - - /* Disable manual control mode: set fan at full speed. */ - if (val == 0) - set_fan_speed(fan_data, fan_data->num_speed - 1); - - mutex_unlock(&fan_data->lock); - - return count; -} - -static ssize_t show_pwm_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "0\n"); -} - -static ssize_t show_rpm_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", fan_data->speed[0].rpm); -} - -static ssize_t show_rpm_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", - fan_data->speed[fan_data->num_speed - 1].rpm); -} - -static ssize_t show_rpm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", fan_data->speed[fan_data->speed_index].rpm); -} - -static ssize_t set_rpm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct gpio_fan_data *fan_data = dev_get_drvdata(dev); - unsigned long rpm; - int ret = count; - - if (kstrtoul(buf, 10, &rpm)) - return -EINVAL; - - mutex_lock(&fan_data->lock); - - if (!fan_data->pwm_enable) { - ret = -EPERM; - goto exit_unlock; - } - - set_fan_speed(fan_data, rpm_to_speed_index(fan_data, rpm)); - -exit_unlock: - mutex_unlock(&fan_data->lock); - - return ret; -} - -static DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm); -static DEVICE_ATTR(pwm1_enable, S_IRUGO | S_IWUSR, - show_pwm_enable, set_pwm_enable); -static DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL); -static DEVICE_ATTR(fan1_min, S_IRUGO, show_rpm_min, NULL); -static DEVICE_ATTR(fan1_max, S_IRUGO, show_rpm_max, NULL); -static DEVICE_ATTR(fan1_input, S_IRUGO, show_rpm, NULL); -static DEVICE_ATTR(fan1_target, S_IRUGO | S_IWUSR, show_rpm, set_rpm); - -static struct attribute *gpio_fan_ctrl_attributes[] = { - &dev_attr_pwm1.attr, - &dev_attr_pwm1_enable.attr, - &dev_attr_pwm1_mode.attr, - &dev_attr_fan1_input.attr, - &dev_attr_fan1_target.attr, - &dev_attr_fan1_min.attr, - &dev_attr_fan1_max.attr, - NULL -}; - -static const struct attribute_group gpio_fan_ctrl_group = { - .attrs = gpio_fan_ctrl_attributes, -}; - -static int fan_ctrl_init(struct gpio_fan_data *fan_data, - struct gpio_fan_platform_data *pdata) -{ - struct platform_device *pdev = fan_data->pdev; - int num_ctrl = pdata->num_ctrl; - unsigned *ctrl = pdata->ctrl; - int i, err; - - for (i = 0; i < num_ctrl; i++) { - err = gpio_request(ctrl[i], "GPIO fan control"); - if (err) - goto err_free_gpio; - - err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i])); - if (err) { - gpio_free(ctrl[i]); - goto err_free_gpio; - } - } - - fan_data->num_ctrl = num_ctrl; - fan_data->ctrl = ctrl; - fan_data->num_speed = pdata->num_speed; - fan_data->speed = pdata->speed; - fan_data->pwm_enable = true; /* Enable manual fan speed control. */ - fan_data->speed_index = get_fan_speed_index(fan_data); - if (fan_data->speed_index < 0) { - err = -ENODEV; - goto err_free_gpio; - } - - err = sysfs_create_group(&pdev->dev.kobj, &gpio_fan_ctrl_group); - if (err) - goto err_free_gpio; - - return 0; - -err_free_gpio: - for (i = i - 1; i >= 0; i--) - gpio_free(ctrl[i]); - - return err; -} - -static void fan_ctrl_free(struct gpio_fan_data *fan_data) -{ - struct platform_device *pdev = fan_data->pdev; - int i; - - sysfs_remove_group(&pdev->dev.kobj, &gpio_fan_ctrl_group); - for (i = 0; i < fan_data->num_ctrl; i++) - gpio_free(fan_data->ctrl[i]); -} - -/* - * Platform driver. - */ - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "gpio-fan\n"); -} - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static int __devinit gpio_fan_probe(struct platform_device *pdev) -{ - int err; - struct gpio_fan_data *fan_data; - struct gpio_fan_platform_data *pdata = pdev->dev.platform_data; - - if (!pdata) - return -EINVAL; - - fan_data = kzalloc(sizeof(struct gpio_fan_data), GFP_KERNEL); - if (!fan_data) - return -ENOMEM; - - fan_data->pdev = pdev; - platform_set_drvdata(pdev, fan_data); - mutex_init(&fan_data->lock); - - /* Configure alarm GPIO if available. */ - if (pdata->alarm) { - err = fan_alarm_init(fan_data, pdata->alarm); - if (err) - goto err_free_data; - } - - /* Configure control GPIOs if available. */ - if (pdata->ctrl && pdata->num_ctrl > 0) { - if (!pdata->speed || pdata->num_speed <= 1) { - err = -EINVAL; - goto err_free_alarm; - } - err = fan_ctrl_init(fan_data, pdata); - if (err) - goto err_free_alarm; - } - - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto err_free_ctrl; - - /* Make this driver part of hwmon class. */ - fan_data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(fan_data->hwmon_dev)) { - err = PTR_ERR(fan_data->hwmon_dev); - goto err_remove_name; - } - - dev_info(&pdev->dev, "GPIO fan initialized\n"); - - return 0; - -err_remove_name: - device_remove_file(&pdev->dev, &dev_attr_name); -err_free_ctrl: - if (fan_data->ctrl) - fan_ctrl_free(fan_data); -err_free_alarm: - if (fan_data->alarm) - fan_alarm_free(fan_data); -err_free_data: - platform_set_drvdata(pdev, NULL); - kfree(fan_data); - - return err; -} - -static int __devexit gpio_fan_remove(struct platform_device *pdev) -{ - struct gpio_fan_data *fan_data = platform_get_drvdata(pdev); - - hwmon_device_unregister(fan_data->hwmon_dev); - device_remove_file(&pdev->dev, &dev_attr_name); - if (fan_data->alarm) - fan_alarm_free(fan_data); - if (fan_data->ctrl) - fan_ctrl_free(fan_data); - kfree(fan_data); - - return 0; -} - -#ifdef CONFIG_PM -static int gpio_fan_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct gpio_fan_data *fan_data = platform_get_drvdata(pdev); - - if (fan_data->ctrl) { - fan_data->resume_speed = fan_data->speed_index; - set_fan_speed(fan_data, 0); - } - - return 0; -} - -static int gpio_fan_resume(struct platform_device *pdev) -{ - struct gpio_fan_data *fan_data = platform_get_drvdata(pdev); - - if (fan_data->ctrl) - set_fan_speed(fan_data, fan_data->resume_speed); - - return 0; -} -#else -#define gpio_fan_suspend NULL -#define gpio_fan_resume NULL -#endif - -static struct platform_driver gpio_fan_driver = { - .probe = gpio_fan_probe, - .remove = __devexit_p(gpio_fan_remove), - .suspend = gpio_fan_suspend, - .resume = gpio_fan_resume, - .driver = { - .name = "gpio-fan", - }, -}; - -module_platform_driver(gpio_fan_driver); - -MODULE_AUTHOR("Simon Guinot "); -MODULE_DESCRIPTION("GPIO FAN driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:gpio-fan"); diff --git a/ANDROID_3.4.5/drivers/hwmon/hwmon-vid.c b/ANDROID_3.4.5/drivers/hwmon/hwmon-vid.c deleted file mode 100644 index 9f264007..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/hwmon-vid.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - * hwmon-vid.c - VID/VRM/VRD voltage conversions - * - * Copyright (c) 2004 Rudolf Marek - * - * Partly imported from i2c-vid.h of the lm_sensors project - * Copyright (c) 2002 Mark D. Studebaker - * With assistance from Trent Piepho - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include - -/* - * Common code for decoding VID pins. - * - * References: - * - * For VRM 8.4 to 9.1, "VRM x.y DC-DC Converter Design Guidelines", - * available at http://developer.intel.com/. - * - * For VRD 10.0 and up, "VRD x.y Design Guide", - * available at http://developer.intel.com/. - * - * AMD Athlon 64 and AMD Opteron Processors, AMD Publication 26094, - * http://support.amd.com/us/Processor_TechDocs/26094.PDF - * Table 74. VID Code Voltages - * This corresponds to an arbitrary VRM code of 24 in the functions below. - * These CPU models (K8 revision <= E) have 5 VID pins. See also: - * Revision Guide for AMD Athlon 64 and AMD Opteron Processors, AMD Publication 25759, - * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25759.pdf - * - * AMD NPT Family 0Fh Processors, AMD Publication 32559, - * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/32559.pdf - * Table 71. VID Code Voltages - * This corresponds to an arbitrary VRM code of 25 in the functions below. - * These CPU models (K8 revision >= F) have 6 VID pins. See also: - * Revision Guide for AMD NPT Family 0Fh Processors, AMD Publication 33610, - * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/33610.pdf - * - * The 17 specification is in fact Intel Mobile Voltage Positioning - - * (IMVP-II). You can find more information in the datasheet of Max1718 - * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2452 - * - * The 13 specification corresponds to the Intel Pentium M series. There - * doesn't seem to be any named specification for these. The conversion - * tables are detailed directly in the various Pentium M datasheets: - * http://www.intel.com/design/intarch/pentiumm/docs_pentiumm.htm - * - * The 14 specification corresponds to Intel Core series. There - * doesn't seem to be any named specification for these. The conversion - * tables are detailed directly in the various Pentium Core datasheets: - * http://www.intel.com/design/mobile/datashts/309221.htm - * - * The 110 (VRM 11) specification corresponds to Intel Conroe based series. - * http://www.intel.com/design/processor/applnots/313214.htm - */ - -/* - * vrm is the VRM/VRD document version multiplied by 10. - * val is the 4-bit or more VID code. - * Returned value is in mV to avoid floating point in the kernel. - * Some VID have some bits in uV scale, this is rounded to mV. - */ -int vid_from_reg(int val, u8 vrm) -{ - int vid; - - switch (vrm) { - - case 100: /* VRD 10.0 */ - /* compute in uV, round to mV */ - val &= 0x3f; - if ((val & 0x1f) == 0x1f) - return 0; - if ((val & 0x1f) <= 0x09 || val == 0x0a) - vid = 1087500 - (val & 0x1f) * 25000; - else - vid = 1862500 - (val & 0x1f) * 25000; - if (val & 0x20) - vid -= 12500; - return (vid + 500) / 1000; - - case 110: /* Intel Conroe */ - /* compute in uV, round to mV */ - val &= 0xff; - if (val < 0x02 || val > 0xb2) - return 0; - return (1600000 - (val - 2) * 6250 + 500) / 1000; - - case 24: /* Athlon64 & Opteron */ - val &= 0x1f; - if (val == 0x1f) - return 0; - /* fall through */ - case 25: /* AMD NPT 0Fh */ - val &= 0x3f; - return (val < 32) ? 1550 - 25 * val - : 775 - (25 * (val - 31)) / 2; - - case 91: /* VRM 9.1 */ - case 90: /* VRM 9.0 */ - val &= 0x1f; - return val == 0x1f ? 0 : - 1850 - val * 25; - - case 85: /* VRM 8.5 */ - val &= 0x1f; - return (val & 0x10 ? 25 : 0) + - ((val & 0x0f) > 0x04 ? 2050 : 1250) - - ((val & 0x0f) * 50); - - case 84: /* VRM 8.4 */ - val &= 0x0f; - /* fall through */ - case 82: /* VRM 8.2 */ - val &= 0x1f; - return val == 0x1f ? 0 : - val & 0x10 ? 5100 - (val) * 100 : - 2050 - (val) * 50; - case 17: /* Intel IMVP-II */ - val &= 0x1f; - return val & 0x10 ? 975 - (val & 0xF) * 25 : - 1750 - val * 50; - case 13: - case 131: - val &= 0x3f; - /* Exception for Eden ULV 500 MHz */ - if (vrm == 131 && val == 0x3f) - val++; - return 1708 - val * 16; - case 14: /* Intel Core */ - /* compute in uV, round to mV */ - val &= 0x7f; - return val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000; - default: /* report 0 for unknown */ - if (vrm) - pr_warn("Requested unsupported VRM version (%u)\n", - (unsigned int)vrm); - return 0; - } -} -EXPORT_SYMBOL(vid_from_reg); - -/* - * After this point is the code to automatically determine which - * VRM/VRD specification should be used depending on the CPU. - */ - -struct vrm_model { - u8 vendor; - u8 family; - u8 model_from; - u8 model_to; - u8 stepping_to; - u8 vrm_type; -}; - -#define ANY 0xFF - -#ifdef CONFIG_X86 - -/* - * The stepping_to parameter is highest acceptable stepping for current line. - * The model match must be exact for 4-bit values. For model values 0x10 - * and above (extended model), all models below the parameter will match. - */ - -static struct vrm_model vrm_models[] = { - {X86_VENDOR_AMD, 0x6, 0x0, ANY, ANY, 90}, /* Athlon Duron etc */ - {X86_VENDOR_AMD, 0xF, 0x0, 0x3F, ANY, 24}, /* Athlon 64, Opteron */ - /* - * In theory, all NPT family 0Fh processors have 6 VID pins and should - * thus use vrm 25, however in practice not all mainboards route the - * 6th VID pin because it is never needed. So we use the 5 VID pin - * variant (vrm 24) for the models which exist today. - */ - {X86_VENDOR_AMD, 0xF, 0x40, 0x7F, ANY, 24}, /* NPT family 0Fh */ - {X86_VENDOR_AMD, 0xF, 0x80, ANY, ANY, 25}, /* future fam. 0Fh */ - {X86_VENDOR_AMD, 0x10, 0x0, ANY, ANY, 25}, /* NPT family 10h */ - - {X86_VENDOR_INTEL, 0x6, 0x0, 0x6, ANY, 82}, /* Pentium Pro, - * Pentium II, Xeon, - * Mobile Pentium, - * Celeron */ - {X86_VENDOR_INTEL, 0x6, 0x7, 0x7, ANY, 84}, /* Pentium III, Xeon */ - {X86_VENDOR_INTEL, 0x6, 0x8, 0x8, ANY, 82}, /* Pentium III, Xeon */ - {X86_VENDOR_INTEL, 0x6, 0x9, 0x9, ANY, 13}, /* Pentium M (130 nm) */ - {X86_VENDOR_INTEL, 0x6, 0xA, 0xA, ANY, 82}, /* Pentium III Xeon */ - {X86_VENDOR_INTEL, 0x6, 0xB, 0xB, ANY, 85}, /* Tualatin */ - {X86_VENDOR_INTEL, 0x6, 0xD, 0xD, ANY, 13}, /* Pentium M (90 nm) */ - {X86_VENDOR_INTEL, 0x6, 0xE, 0xE, ANY, 14}, /* Intel Core (65 nm) */ - {X86_VENDOR_INTEL, 0x6, 0xF, ANY, ANY, 110}, /* Intel Conroe and - * later */ - {X86_VENDOR_INTEL, 0xF, 0x0, 0x0, ANY, 90}, /* P4 */ - {X86_VENDOR_INTEL, 0xF, 0x1, 0x1, ANY, 90}, /* P4 Willamette */ - {X86_VENDOR_INTEL, 0xF, 0x2, 0x2, ANY, 90}, /* P4 Northwood */ - {X86_VENDOR_INTEL, 0xF, 0x3, ANY, ANY, 100}, /* Prescott and above - * assume VRD 10 */ - - {X86_VENDOR_CENTAUR, 0x6, 0x7, 0x7, ANY, 85}, /* Eden ESP/Ezra */ - {X86_VENDOR_CENTAUR, 0x6, 0x8, 0x8, 0x7, 85}, /* Ezra T */ - {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x9, 0x7, 85}, /* Nehemiah */ - {X86_VENDOR_CENTAUR, 0x6, 0x9, 0x9, ANY, 17}, /* C3-M, Eden-N */ - {X86_VENDOR_CENTAUR, 0x6, 0xA, 0xA, 0x7, 0}, /* No information */ - {X86_VENDOR_CENTAUR, 0x6, 0xA, 0xA, ANY, 13}, /* C7-M, C7, - * Eden (Esther) */ - {X86_VENDOR_CENTAUR, 0x6, 0xD, 0xD, ANY, 134}, /* C7-D, C7-M, C7, - * Eden (Esther) */ -}; - -/* - * Special case for VIA model D: there are two different possible - * VID tables, so we have to figure out first, which one must be - * used. This resolves temporary drm value 134 to 14 (Intel Core - * 7-bit VID), 13 (Pentium M 6-bit VID) or 131 (Pentium M 6-bit VID - * + quirk for Eden ULV 500 MHz). - * Note: something similar might be needed for model A, I'm not sure. - */ -static u8 get_via_model_d_vrm(void) -{ - unsigned int vid, brand, dummy; - static const char *brands[4] = { - "C7-M", "C7", "Eden", "C7-D" - }; - - rdmsr(0x198, dummy, vid); - vid &= 0xff; - - rdmsr(0x1154, brand, dummy); - brand = ((brand >> 4) ^ (brand >> 2)) & 0x03; - - if (vid > 0x3f) { - pr_info("Using %d-bit VID table for VIA %s CPU\n", - 7, brands[brand]); - return 14; - } else { - pr_info("Using %d-bit VID table for VIA %s CPU\n", - 6, brands[brand]); - /* Enable quirk for Eden */ - return brand == 2 ? 131 : 13; - } -} - -static u8 find_vrm(u8 family, u8 model, u8 stepping, u8 vendor) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(vrm_models); i++) { - if (vendor == vrm_models[i].vendor && - family == vrm_models[i].family && - model >= vrm_models[i].model_from && - model <= vrm_models[i].model_to && - stepping <= vrm_models[i].stepping_to) - return vrm_models[i].vrm_type; - } - - return 0; -} - -u8 vid_which_vrm(void) -{ - struct cpuinfo_x86 *c = &cpu_data(0); - u8 vrm_ret; - - if (c->x86 < 6) /* Any CPU with family lower than 6 */ - return 0; /* doesn't have VID */ - - vrm_ret = find_vrm(c->x86, c->x86_model, c->x86_mask, c->x86_vendor); - if (vrm_ret == 134) - vrm_ret = get_via_model_d_vrm(); - if (vrm_ret == 0) - pr_info("Unknown VRM version of your x86 CPU\n"); - return vrm_ret; -} - -/* and now for something completely different for the non-x86 world */ -#else -u8 vid_which_vrm(void) -{ - pr_info("Unknown VRM version of your CPU\n"); - return 0; -} -#endif -EXPORT_SYMBOL(vid_which_vrm); - -MODULE_AUTHOR("Rudolf Marek "); - -MODULE_DESCRIPTION("hwmon-vid driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/hwmon.c b/ANDROID_3.4.5/drivers/hwmon/hwmon.c deleted file mode 100644 index c3c471ca..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/hwmon.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring - * - * This file defines the sysfs class "hwmon", for use by sensors drivers. - * - * Copyright (C) 2005 Mark M. Hoffman - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define HWMON_ID_PREFIX "hwmon" -#define HWMON_ID_FORMAT HWMON_ID_PREFIX "%d" - -static struct class *hwmon_class; - -static DEFINE_IDA(hwmon_ida); - -/** - * hwmon_device_register - register w/ hwmon - * @dev: the device to register - * - * hwmon_device_unregister() must be called when the device is no - * longer needed. - * - * Returns the pointer to the new device. - */ -struct device *hwmon_device_register(struct device *dev) -{ - struct device *hwdev; - int id; - - id = ida_simple_get(&hwmon_ida, 0, 0, GFP_KERNEL); - if (id < 0) - return ERR_PTR(id); - - hwdev = device_create(hwmon_class, dev, MKDEV(0, 0), NULL, - HWMON_ID_FORMAT, id); - - if (IS_ERR(hwdev)) - ida_simple_remove(&hwmon_ida, id); - - return hwdev; -} -EXPORT_SYMBOL_GPL(hwmon_device_register); - -/** - * hwmon_device_unregister - removes the previously registered class device - * - * @dev: the class device to destroy - */ -void hwmon_device_unregister(struct device *dev) -{ - int id; - - if (likely(sscanf(dev_name(dev), HWMON_ID_FORMAT, &id) == 1)) { - device_unregister(dev); - ida_simple_remove(&hwmon_ida, id); - } else - dev_dbg(dev->parent, - "hwmon_device_unregister() failed: bad class ID!\n"); -} -EXPORT_SYMBOL_GPL(hwmon_device_unregister); - -static void __init hwmon_pci_quirks(void) -{ -#if defined CONFIG_X86 && defined CONFIG_PCI - struct pci_dev *sb; - u16 base; - u8 enable; - - /* Open access to 0x295-0x296 on MSI MS-7031 */ - sb = pci_get_device(PCI_VENDOR_ID_ATI, 0x436c, NULL); - if (sb && - (sb->subsystem_vendor == 0x1462 && /* MSI */ - sb->subsystem_device == 0x0031)) { /* MS-7031 */ - - pci_read_config_byte(sb, 0x48, &enable); - pci_read_config_word(sb, 0x64, &base); - - if (base == 0 && !(enable & BIT(2))) { - dev_info(&sb->dev, - "Opening wide generic port at 0x295\n"); - pci_write_config_word(sb, 0x64, 0x295); - pci_write_config_byte(sb, 0x48, enable | BIT(2)); - } - } -#endif -} - -static int __init hwmon_init(void) -{ - hwmon_pci_quirks(); - - hwmon_class = class_create(THIS_MODULE, "hwmon"); - if (IS_ERR(hwmon_class)) { - pr_err("couldn't create sysfs class\n"); - return PTR_ERR(hwmon_class); - } - return 0; -} - -static void __exit hwmon_exit(void) -{ - class_destroy(hwmon_class); -} - -subsys_initcall(hwmon_init); -module_exit(hwmon_exit); - -MODULE_AUTHOR("Mark M. Hoffman "); -MODULE_DESCRIPTION("hardware monitoring sysfs/class support"); -MODULE_LICENSE("GPL"); - diff --git a/ANDROID_3.4.5/drivers/hwmon/i5k_amb.c b/ANDROID_3.4.5/drivers/hwmon/i5k_amb.c deleted file mode 100644 index a18882cc..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/i5k_amb.c +++ /dev/null @@ -1,621 +0,0 @@ -/* - * A hwmon driver for the Intel 5000 series chipset FB-DIMM AMB - * temperature sensors - * Copyright (C) 2007 IBM - * - * Author: Darrick J. Wong - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "i5k_amb" - -#define I5K_REG_AMB_BASE_ADDR 0x48 -#define I5K_REG_AMB_LEN_ADDR 0x50 -#define I5K_REG_CHAN0_PRESENCE_ADDR 0x64 -#define I5K_REG_CHAN1_PRESENCE_ADDR 0x66 - -#define AMB_REG_TEMP_MIN_ADDR 0x80 -#define AMB_REG_TEMP_MID_ADDR 0x81 -#define AMB_REG_TEMP_MAX_ADDR 0x82 -#define AMB_REG_TEMP_STATUS_ADDR 0x84 -#define AMB_REG_TEMP_ADDR 0x85 - -#define AMB_CONFIG_SIZE 2048 -#define AMB_FUNC_3_OFFSET 768 - -static unsigned long amb_reg_temp_status(unsigned int amb) -{ - return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_STATUS_ADDR + - AMB_CONFIG_SIZE * amb; -} - -static unsigned long amb_reg_temp_min(unsigned int amb) -{ - return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MIN_ADDR + - AMB_CONFIG_SIZE * amb; -} - -static unsigned long amb_reg_temp_mid(unsigned int amb) -{ - return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MID_ADDR + - AMB_CONFIG_SIZE * amb; -} - -static unsigned long amb_reg_temp_max(unsigned int amb) -{ - return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_MAX_ADDR + - AMB_CONFIG_SIZE * amb; -} - -static unsigned long amb_reg_temp(unsigned int amb) -{ - return AMB_FUNC_3_OFFSET + AMB_REG_TEMP_ADDR + - AMB_CONFIG_SIZE * amb; -} - -#define MAX_MEM_CHANNELS 4 -#define MAX_AMBS_PER_CHANNEL 16 -#define MAX_AMBS (MAX_MEM_CHANNELS * \ - MAX_AMBS_PER_CHANNEL) -#define CHANNEL_SHIFT 4 -#define DIMM_MASK 0xF -/* - * Ugly hack: For some reason the highest bit is set if there - * are _any_ DIMMs in the channel. Attempting to read from - * this "high-order" AMB results in a memory bus error, so - * for now we'll just ignore that top bit, even though that - * might prevent us from seeing the 16th DIMM in the channel. - */ -#define REAL_MAX_AMBS_PER_CHANNEL 15 -#define KNOBS_PER_AMB 6 - -static unsigned long amb_num_from_reg(unsigned int byte_num, unsigned int bit) -{ - return byte_num * MAX_AMBS_PER_CHANNEL + bit; -} - -#define AMB_SYSFS_NAME_LEN 16 -struct i5k_device_attribute { - struct sensor_device_attribute s_attr; - char name[AMB_SYSFS_NAME_LEN]; -}; - -struct i5k_amb_data { - struct device *hwmon_dev; - - unsigned long amb_base; - unsigned long amb_len; - u16 amb_present[MAX_MEM_CHANNELS]; - void __iomem *amb_mmio; - struct i5k_device_attribute *attrs; - unsigned int num_attrs; -}; - -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - return sprintf(buf, "%s\n", DRVNAME); -} - - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct platform_device *amb_pdev; - -static u8 amb_read_byte(struct i5k_amb_data *data, unsigned long offset) -{ - return ioread8(data->amb_mmio + offset); -} - -static void amb_write_byte(struct i5k_amb_data *data, unsigned long offset, - u8 val) -{ - iowrite8(val, data->amb_mmio + offset); -} - -static ssize_t show_amb_alarm(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - - if (!(amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x20) && - (amb_read_byte(data, amb_reg_temp_status(attr->index)) & 0x8)) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_amb_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - unsigned long temp; - int ret = kstrtoul(buf, 10, &temp); - if (ret < 0) - return ret; - - temp = temp / 500; - if (temp > 255) - temp = 255; - - amb_write_byte(data, amb_reg_temp_min(attr->index), temp); - return count; -} - -static ssize_t store_amb_mid(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - unsigned long temp; - int ret = kstrtoul(buf, 10, &temp); - if (ret < 0) - return ret; - - temp = temp / 500; - if (temp > 255) - temp = 255; - - amb_write_byte(data, amb_reg_temp_mid(attr->index), temp); - return count; -} - -static ssize_t store_amb_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - unsigned long temp; - int ret = kstrtoul(buf, 10, &temp); - if (ret < 0) - return ret; - - temp = temp / 500; - if (temp > 255) - temp = 255; - - amb_write_byte(data, amb_reg_temp_max(attr->index), temp); - return count; -} - -static ssize_t show_amb_min(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - 500 * amb_read_byte(data, amb_reg_temp_min(attr->index))); -} - -static ssize_t show_amb_mid(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - 500 * amb_read_byte(data, amb_reg_temp_mid(attr->index))); -} - -static ssize_t show_amb_max(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - 500 * amb_read_byte(data, amb_reg_temp_max(attr->index))); -} - -static ssize_t show_amb_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i5k_amb_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", - 500 * amb_read_byte(data, amb_reg_temp(attr->index))); -} - -static ssize_t show_label(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - - return sprintf(buf, "Ch. %d DIMM %d\n", attr->index >> CHANNEL_SHIFT, - attr->index & DIMM_MASK); -} - -static int __devinit i5k_amb_hwmon_init(struct platform_device *pdev) -{ - int i, j, k, d = 0; - u16 c; - int res = 0; - int num_ambs = 0; - struct i5k_amb_data *data = platform_get_drvdata(pdev); - - /* Count the number of AMBs found */ - /* ignore the high-order bit, see "Ugly hack" comment above */ - for (i = 0; i < MAX_MEM_CHANNELS; i++) - num_ambs += hweight16(data->amb_present[i] & 0x7fff); - - /* Set up sysfs stuff */ - data->attrs = kzalloc(sizeof(*data->attrs) * num_ambs * KNOBS_PER_AMB, - GFP_KERNEL); - if (!data->attrs) - return -ENOMEM; - data->num_attrs = 0; - - for (i = 0; i < MAX_MEM_CHANNELS; i++) { - c = data->amb_present[i]; - for (j = 0; j < REAL_MAX_AMBS_PER_CHANNEL; j++, c >>= 1) { - struct i5k_device_attribute *iattr; - - k = amb_num_from_reg(i, j); - if (!(c & 0x1)) - continue; - d++; - - /* sysfs label */ - iattr = data->attrs + data->num_attrs; - snprintf(iattr->name, AMB_SYSFS_NAME_LEN, - "temp%d_label", d); - iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IRUGO; - iattr->s_attr.dev_attr.show = show_label; - iattr->s_attr.index = k; - sysfs_attr_init(&iattr->s_attr.dev_attr.attr); - res = device_create_file(&pdev->dev, - &iattr->s_attr.dev_attr); - if (res) - goto exit_remove; - data->num_attrs++; - - /* Temperature sysfs knob */ - iattr = data->attrs + data->num_attrs; - snprintf(iattr->name, AMB_SYSFS_NAME_LEN, - "temp%d_input", d); - iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IRUGO; - iattr->s_attr.dev_attr.show = show_amb_temp; - iattr->s_attr.index = k; - sysfs_attr_init(&iattr->s_attr.dev_attr.attr); - res = device_create_file(&pdev->dev, - &iattr->s_attr.dev_attr); - if (res) - goto exit_remove; - data->num_attrs++; - - /* Temperature min sysfs knob */ - iattr = data->attrs + data->num_attrs; - snprintf(iattr->name, AMB_SYSFS_NAME_LEN, - "temp%d_min", d); - iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; - iattr->s_attr.dev_attr.show = show_amb_min; - iattr->s_attr.dev_attr.store = store_amb_min; - iattr->s_attr.index = k; - sysfs_attr_init(&iattr->s_attr.dev_attr.attr); - res = device_create_file(&pdev->dev, - &iattr->s_attr.dev_attr); - if (res) - goto exit_remove; - data->num_attrs++; - - /* Temperature mid sysfs knob */ - iattr = data->attrs + data->num_attrs; - snprintf(iattr->name, AMB_SYSFS_NAME_LEN, - "temp%d_mid", d); - iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; - iattr->s_attr.dev_attr.show = show_amb_mid; - iattr->s_attr.dev_attr.store = store_amb_mid; - iattr->s_attr.index = k; - sysfs_attr_init(&iattr->s_attr.dev_attr.attr); - res = device_create_file(&pdev->dev, - &iattr->s_attr.dev_attr); - if (res) - goto exit_remove; - data->num_attrs++; - - /* Temperature max sysfs knob */ - iattr = data->attrs + data->num_attrs; - snprintf(iattr->name, AMB_SYSFS_NAME_LEN, - "temp%d_max", d); - iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IWUSR | S_IRUGO; - iattr->s_attr.dev_attr.show = show_amb_max; - iattr->s_attr.dev_attr.store = store_amb_max; - iattr->s_attr.index = k; - sysfs_attr_init(&iattr->s_attr.dev_attr.attr); - res = device_create_file(&pdev->dev, - &iattr->s_attr.dev_attr); - if (res) - goto exit_remove; - data->num_attrs++; - - /* Temperature alarm sysfs knob */ - iattr = data->attrs + data->num_attrs; - snprintf(iattr->name, AMB_SYSFS_NAME_LEN, - "temp%d_alarm", d); - iattr->s_attr.dev_attr.attr.name = iattr->name; - iattr->s_attr.dev_attr.attr.mode = S_IRUGO; - iattr->s_attr.dev_attr.show = show_amb_alarm; - iattr->s_attr.index = k; - sysfs_attr_init(&iattr->s_attr.dev_attr.attr); - res = device_create_file(&pdev->dev, - &iattr->s_attr.dev_attr); - if (res) - goto exit_remove; - data->num_attrs++; - } - } - - res = device_create_file(&pdev->dev, &dev_attr_name); - if (res) - goto exit_remove; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - res = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return res; - -exit_remove: - device_remove_file(&pdev->dev, &dev_attr_name); - for (i = 0; i < data->num_attrs; i++) - device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr); - kfree(data->attrs); - - return res; -} - -static int __devinit i5k_amb_add(void) -{ - int res = -ENODEV; - - /* only ever going to be one of these */ - amb_pdev = platform_device_alloc(DRVNAME, 0); - if (!amb_pdev) - return -ENOMEM; - - res = platform_device_add(amb_pdev); - if (res) - goto err; - return 0; - -err: - platform_device_put(amb_pdev); - return res; -} - -static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data, - unsigned long devid) -{ - struct pci_dev *pcidev; - u32 val32; - int res = -ENODEV; - - /* Find AMB register memory space */ - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, - devid, - NULL); - if (!pcidev) - return -ENODEV; - - if (pci_read_config_dword(pcidev, I5K_REG_AMB_BASE_ADDR, &val32)) - goto out; - data->amb_base = val32; - - if (pci_read_config_dword(pcidev, I5K_REG_AMB_LEN_ADDR, &val32)) - goto out; - data->amb_len = val32; - - /* Is it big enough? */ - if (data->amb_len < AMB_CONFIG_SIZE * MAX_AMBS) { - dev_err(&pcidev->dev, "AMB region too small!\n"); - goto out; - } - - res = 0; -out: - pci_dev_put(pcidev); - return res; -} - -static int __devinit i5k_channel_probe(u16 *amb_present, unsigned long dev_id) -{ - struct pci_dev *pcidev; - u16 val16; - int res = -ENODEV; - - /* Copy the DIMM presence map for these two channels */ - pcidev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); - if (!pcidev) - return -ENODEV; - - if (pci_read_config_word(pcidev, I5K_REG_CHAN0_PRESENCE_ADDR, &val16)) - goto out; - amb_present[0] = val16; - - if (pci_read_config_word(pcidev, I5K_REG_CHAN1_PRESENCE_ADDR, &val16)) - goto out; - amb_present[1] = val16; - - res = 0; - -out: - pci_dev_put(pcidev); - return res; -} - -static struct { - unsigned long err; - unsigned long fbd0; -} chipset_ids[] __devinitdata = { - { PCI_DEVICE_ID_INTEL_5000_ERR, PCI_DEVICE_ID_INTEL_5000_FBD0 }, - { PCI_DEVICE_ID_INTEL_5400_ERR, PCI_DEVICE_ID_INTEL_5400_FBD0 }, - { 0, 0 } -}; - -#ifdef MODULE -static struct pci_device_id i5k_amb_ids[] __devinitdata = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5000_ERR) }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_5400_ERR) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, i5k_amb_ids); -#endif - -static int __devinit i5k_amb_probe(struct platform_device *pdev) -{ - struct i5k_amb_data *data; - struct resource *reso; - int i, res; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - /* Figure out where the AMB registers live */ - i = 0; - do { - res = i5k_find_amb_registers(data, chipset_ids[i].err); - if (res == 0) - break; - i++; - } while (chipset_ids[i].err); - - if (res) - goto err; - - /* Copy the DIMM presence map for the first two channels */ - res = i5k_channel_probe(&data->amb_present[0], chipset_ids[i].fbd0); - if (res) - goto err; - - /* Copy the DIMM presence map for the optional second two channels */ - i5k_channel_probe(&data->amb_present[2], chipset_ids[i].fbd0 + 1); - - /* Set up resource regions */ - reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME); - if (!reso) { - res = -EBUSY; - goto err; - } - - data->amb_mmio = ioremap_nocache(data->amb_base, data->amb_len); - if (!data->amb_mmio) { - res = -EBUSY; - goto err_map_failed; - } - - platform_set_drvdata(pdev, data); - - res = i5k_amb_hwmon_init(pdev); - if (res) - goto err_init_failed; - - return res; - -err_init_failed: - iounmap(data->amb_mmio); - platform_set_drvdata(pdev, NULL); -err_map_failed: - release_mem_region(data->amb_base, data->amb_len); -err: - kfree(data); - return res; -} - -static int __devexit i5k_amb_remove(struct platform_device *pdev) -{ - int i; - struct i5k_amb_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - device_remove_file(&pdev->dev, &dev_attr_name); - for (i = 0; i < data->num_attrs; i++) - device_remove_file(&pdev->dev, &data->attrs[i].s_attr.dev_attr); - kfree(data->attrs); - iounmap(data->amb_mmio); - release_mem_region(data->amb_base, data->amb_len); - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; -} - -static struct platform_driver i5k_amb_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = i5k_amb_probe, - .remove = __devexit_p(i5k_amb_remove), -}; - -static int __init i5k_amb_init(void) -{ - int res; - - res = platform_driver_register(&i5k_amb_driver); - if (res) - return res; - - res = i5k_amb_add(); - if (res) - platform_driver_unregister(&i5k_amb_driver); - - return res; -} - -static void __exit i5k_amb_exit(void) -{ - platform_device_unregister(amb_pdev); - platform_driver_unregister(&i5k_amb_driver); -} - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("Intel 5000 chipset FB-DIMM AMB temperature sensor"); -MODULE_LICENSE("GPL"); - -module_init(i5k_amb_init); -module_exit(i5k_amb_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/ibmaem.c b/ANDROID_3.4.5/drivers/hwmon/ibmaem.c deleted file mode 100644 index 37f17e0d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ibmaem.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * A hwmon driver for the IBM System Director Active Energy Manager (AEM) - * temperature/power/energy sensors and capping functionality. - * Copyright (C) 2008 IBM - * - * Author: Darrick J. Wong - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define REFRESH_INTERVAL (HZ) -#define IPMI_TIMEOUT (30 * HZ) -#define DRVNAME "aem" - -#define AEM_NETFN 0x2E - -#define AEM_FIND_FW_CMD 0x80 -#define AEM_ELEMENT_CMD 0x81 -#define AEM_FW_INSTANCE_CMD 0x82 - -#define AEM_READ_ELEMENT_CFG 0x80 -#define AEM_READ_BUFFER 0x81 -#define AEM_READ_REGISTER 0x82 -#define AEM_WRITE_REGISTER 0x83 -#define AEM_SET_REG_MASK 0x84 -#define AEM_CLEAR_REG_MASK 0x85 -#define AEM_READ_ELEMENT_CFG2 0x86 - -#define AEM_CONTROL_ELEMENT 0 -#define AEM_ENERGY_ELEMENT 1 -#define AEM_CLOCK_ELEMENT 4 -#define AEM_POWER_CAP_ELEMENT 7 -#define AEM_EXHAUST_ELEMENT 9 -#define AEM_POWER_ELEMENT 10 - -#define AEM_MODULE_TYPE_ID 0x0001 - -#define AEM2_NUM_ENERGY_REGS 2 -#define AEM2_NUM_PCAP_REGS 6 -#define AEM2_NUM_TEMP_REGS 2 -#define AEM2_NUM_SENSORS 14 - -#define AEM1_NUM_ENERGY_REGS 1 -#define AEM1_NUM_SENSORS 3 - -/* AEM 2.x has more energy registers */ -#define AEM_NUM_ENERGY_REGS AEM2_NUM_ENERGY_REGS -/* AEM 2.x needs more sensor files */ -#define AEM_NUM_SENSORS AEM2_NUM_SENSORS - -#define POWER_CAP 0 -#define POWER_CAP_MAX_HOTPLUG 1 -#define POWER_CAP_MAX 2 -#define POWER_CAP_MIN_WARNING 3 -#define POWER_CAP_MIN 4 -#define POWER_AUX 5 - -#define AEM_DEFAULT_POWER_INTERVAL 1000 -#define AEM_MIN_POWER_INTERVAL 200 -#define UJ_PER_MJ 1000L - -static DEFINE_IDA(aem_ida); - -static struct platform_driver aem_driver = { - .driver = { - .name = DRVNAME, - .bus = &platform_bus_type, - } -}; - -struct aem_ipmi_data { - struct completion read_complete; - struct ipmi_addr address; - ipmi_user_t user; - int interface; - - struct kernel_ipmi_msg tx_message; - long tx_msgid; - - void *rx_msg_data; - unsigned short rx_msg_len; - unsigned char rx_result; - int rx_recv_type; - - struct device *bmc_device; -}; - -struct aem_ro_sensor_template { - char *label; - ssize_t (*show)(struct device *dev, - struct device_attribute *devattr, - char *buf); - int index; -}; - -struct aem_rw_sensor_template { - char *label; - ssize_t (*show)(struct device *dev, - struct device_attribute *devattr, - char *buf); - ssize_t (*set)(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count); - int index; -}; - -struct aem_data { - struct list_head list; - - struct device *hwmon_dev; - struct platform_device *pdev; - struct mutex lock; - char valid; - unsigned long last_updated; /* In jiffies */ - u8 ver_major; - u8 ver_minor; - u8 module_handle; - int id; - struct aem_ipmi_data ipmi; - - /* Function and buffer to update sensors */ - void (*update)(struct aem_data *data); - struct aem_read_sensor_resp *rs_resp; - - /* - * AEM 1.x sensors: - * Available sensors: - * Energy meter - * Power meter - * - * AEM 2.x sensors: - * Two energy meters - * Two power meters - * Two temperature sensors - * Six power cap registers - */ - - /* sysfs attrs */ - struct sensor_device_attribute sensors[AEM_NUM_SENSORS]; - - /* energy use in mJ */ - u64 energy[AEM_NUM_ENERGY_REGS]; - - /* power sampling interval in ms */ - unsigned long power_period[AEM_NUM_ENERGY_REGS]; - - /* Everything past here is for AEM2 only */ - - /* power caps in dW */ - u16 pcap[AEM2_NUM_PCAP_REGS]; - - /* exhaust temperature in C */ - u8 temp[AEM2_NUM_TEMP_REGS]; -}; - -/* Data structures returned by the AEM firmware */ -struct aem_iana_id { - u8 bytes[3]; -}; -static struct aem_iana_id system_x_id = { - .bytes = {0x4D, 0x4F, 0x00} -}; - -/* These are used to find AEM1 instances */ -struct aem_find_firmware_req { - struct aem_iana_id id; - u8 rsvd; - __be16 index; - __be16 module_type_id; -} __packed; - -struct aem_find_firmware_resp { - struct aem_iana_id id; - u8 num_instances; -} __packed; - -/* These are used to find AEM2 instances */ -struct aem_find_instance_req { - struct aem_iana_id id; - u8 instance_number; - __be16 module_type_id; -} __packed; - -struct aem_find_instance_resp { - struct aem_iana_id id; - u8 num_instances; - u8 major; - u8 minor; - u8 module_handle; - u16 record_id; -} __packed; - -/* These are used to query sensors */ -struct aem_read_sensor_req { - struct aem_iana_id id; - u8 module_handle; - u8 element; - u8 subcommand; - u8 reg; - u8 rx_buf_size; -} __packed; - -struct aem_read_sensor_resp { - struct aem_iana_id id; - u8 bytes[0]; -} __packed; - -/* Data structures to talk to the IPMI layer */ -struct aem_driver_data { - struct list_head aem_devices; - struct ipmi_smi_watcher bmc_events; - struct ipmi_user_hndl ipmi_hndlrs; -}; - -static void aem_register_bmc(int iface, struct device *dev); -static void aem_bmc_gone(int iface); -static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); - -static void aem_remove_sensors(struct aem_data *data); -static int aem1_find_sensors(struct aem_data *data); -static int aem2_find_sensors(struct aem_data *data); -static void update_aem1_sensors(struct aem_data *data); -static void update_aem2_sensors(struct aem_data *data); - -static struct aem_driver_data driver_data = { - .aem_devices = LIST_HEAD_INIT(driver_data.aem_devices), - .bmc_events = { - .owner = THIS_MODULE, - .new_smi = aem_register_bmc, - .smi_gone = aem_bmc_gone, - }, - .ipmi_hndlrs = { - .ipmi_recv_hndl = aem_msg_handler, - }, -}; - -/* Functions to talk to the IPMI layer */ - -/* Initialize IPMI address, message buffers and user data */ -static int aem_init_ipmi_data(struct aem_ipmi_data *data, int iface, - struct device *bmc) -{ - int err; - - init_completion(&data->read_complete); - data->bmc_device = bmc; - - /* Initialize IPMI address */ - data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; - data->address.channel = IPMI_BMC_CHANNEL; - data->address.data[0] = 0; - data->interface = iface; - - /* Initialize message buffers */ - data->tx_msgid = 0; - data->tx_message.netfn = AEM_NETFN; - - /* Create IPMI messaging interface user */ - err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs, - data, &data->user); - if (err < 0) { - dev_err(bmc, "Unable to register user with IPMI " - "interface %d\n", data->interface); - return -EACCES; - } - - return 0; -} - -/* Send an IPMI command */ -static int aem_send_message(struct aem_ipmi_data *data) -{ - int err; - - err = ipmi_validate_addr(&data->address, sizeof(data->address)); - if (err) - goto out; - - data->tx_msgid++; - err = ipmi_request_settime(data->user, &data->address, data->tx_msgid, - &data->tx_message, data, 0, 0, 0); - if (err) - goto out1; - - return 0; -out1: - dev_err(data->bmc_device, "request_settime=%x\n", err); - return err; -out: - dev_err(data->bmc_device, "validate_addr=%x\n", err); - return err; -} - -/* Dispatch IPMI messages to callers */ -static void aem_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) -{ - unsigned short rx_len; - struct aem_ipmi_data *data = user_msg_data; - - if (msg->msgid != data->tx_msgid) { - dev_err(data->bmc_device, "Mismatch between received msgid " - "(%02x) and transmitted msgid (%02x)!\n", - (int)msg->msgid, - (int)data->tx_msgid); - ipmi_free_recv_msg(msg); - return; - } - - data->rx_recv_type = msg->recv_type; - if (msg->msg.data_len > 0) - data->rx_result = msg->msg.data[0]; - else - data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; - - if (msg->msg.data_len > 1) { - rx_len = msg->msg.data_len - 1; - if (data->rx_msg_len < rx_len) - rx_len = data->rx_msg_len; - data->rx_msg_len = rx_len; - memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len); - } else - data->rx_msg_len = 0; - - ipmi_free_recv_msg(msg); - complete(&data->read_complete); -} - -/* Sensor support functions */ - -/* Read a sensor value; must be called with data->lock held */ -static int aem_read_sensor(struct aem_data *data, u8 elt, u8 reg, - void *buf, size_t size) -{ - int rs_size, res; - struct aem_read_sensor_req rs_req; - /* Use preallocated rx buffer */ - struct aem_read_sensor_resp *rs_resp = data->rs_resp; - struct aem_ipmi_data *ipmi = &data->ipmi; - - /* AEM registers are 1, 2, 4 or 8 bytes */ - switch (size) { - case 1: - case 2: - case 4: - case 8: - break; - default: - return -EINVAL; - } - - rs_req.id = system_x_id; - rs_req.module_handle = data->module_handle; - rs_req.element = elt; - rs_req.subcommand = AEM_READ_REGISTER; - rs_req.reg = reg; - rs_req.rx_buf_size = size; - - ipmi->tx_message.cmd = AEM_ELEMENT_CMD; - ipmi->tx_message.data = (char *)&rs_req; - ipmi->tx_message.data_len = sizeof(rs_req); - - rs_size = sizeof(*rs_resp) + size; - ipmi->rx_msg_data = rs_resp; - ipmi->rx_msg_len = rs_size; - - aem_send_message(ipmi); - - res = wait_for_completion_timeout(&ipmi->read_complete, IPMI_TIMEOUT); - if (!res) { - res = -ETIMEDOUT; - goto out; - } - - if (ipmi->rx_result || ipmi->rx_msg_len != rs_size || - memcmp(&rs_resp->id, &system_x_id, sizeof(system_x_id))) { - res = -ENOENT; - goto out; - } - - switch (size) { - case 1: { - u8 *x = buf; - *x = rs_resp->bytes[0]; - break; - } - case 2: { - u16 *x = buf; - *x = be16_to_cpup((__be16 *)rs_resp->bytes); - break; - } - case 4: { - u32 *x = buf; - *x = be32_to_cpup((__be32 *)rs_resp->bytes); - break; - } - case 8: { - u64 *x = buf; - *x = be64_to_cpup((__be64 *)rs_resp->bytes); - break; - } - } - res = 0; - -out: - return res; -} - -/* Update AEM energy registers */ -static void update_aem_energy_one(struct aem_data *data, int which) -{ - aem_read_sensor(data, AEM_ENERGY_ELEMENT, which, - &data->energy[which], 8); -} - -static void update_aem_energy(struct aem_data *data) -{ - update_aem_energy_one(data, 0); - if (data->ver_major < 2) - return; - update_aem_energy_one(data, 1); -} - -/* Update all AEM1 sensors */ -static void update_aem1_sensors(struct aem_data *data) -{ - mutex_lock(&data->lock); - if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) && - data->valid) - goto out; - - update_aem_energy(data); -out: - mutex_unlock(&data->lock); -} - -/* Update all AEM2 sensors */ -static void update_aem2_sensors(struct aem_data *data) -{ - int i; - - mutex_lock(&data->lock); - if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) && - data->valid) - goto out; - - update_aem_energy(data); - aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 0, &data->temp[0], 1); - aem_read_sensor(data, AEM_EXHAUST_ELEMENT, 1, &data->temp[1], 1); - - for (i = POWER_CAP; i <= POWER_AUX; i++) - aem_read_sensor(data, AEM_POWER_CAP_ELEMENT, i, - &data->pcap[i], 2); -out: - mutex_unlock(&data->lock); -} - -/* Delete an AEM instance */ -static void aem_delete(struct aem_data *data) -{ - list_del(&data->list); - aem_remove_sensors(data); - kfree(data->rs_resp); - hwmon_device_unregister(data->hwmon_dev); - ipmi_destroy_user(data->ipmi.user); - platform_set_drvdata(data->pdev, NULL); - platform_device_unregister(data->pdev); - ida_simple_remove(&aem_ida, data->id); - kfree(data); -} - -/* Probe functions for AEM1 devices */ - -/* Retrieve version and module handle for an AEM1 instance */ -static int aem_find_aem1_count(struct aem_ipmi_data *data) -{ - int res; - struct aem_find_firmware_req ff_req; - struct aem_find_firmware_resp ff_resp; - - ff_req.id = system_x_id; - ff_req.index = 0; - ff_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID); - - data->tx_message.cmd = AEM_FIND_FW_CMD; - data->tx_message.data = (char *)&ff_req; - data->tx_message.data_len = sizeof(ff_req); - - data->rx_msg_data = &ff_resp; - data->rx_msg_len = sizeof(ff_resp); - - aem_send_message(data); - - res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT); - if (!res) - return -ETIMEDOUT; - - if (data->rx_result || data->rx_msg_len != sizeof(ff_resp) || - memcmp(&ff_resp.id, &system_x_id, sizeof(system_x_id))) - return -ENOENT; - - return ff_resp.num_instances; -} - -/* Find and initialize one AEM1 instance */ -static int aem_init_aem1_inst(struct aem_ipmi_data *probe, u8 module_handle) -{ - struct aem_data *data; - int i; - int res = -ENOMEM; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return res; - mutex_init(&data->lock); - - /* Copy instance data */ - data->ver_major = 1; - data->ver_minor = 0; - data->module_handle = module_handle; - for (i = 0; i < AEM1_NUM_ENERGY_REGS; i++) - data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL; - - /* Create sub-device for this fw instance */ - data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL); - if (data->id < 0) - goto id_err; - - data->pdev = platform_device_alloc(DRVNAME, data->id); - if (!data->pdev) - goto dev_err; - data->pdev->dev.driver = &aem_driver.driver; - - res = platform_device_add(data->pdev); - if (res) - goto ipmi_err; - - platform_set_drvdata(data->pdev, data); - - /* Set up IPMI interface */ - res = aem_init_ipmi_data(&data->ipmi, probe->interface, - probe->bmc_device); - if (res) - goto ipmi_err; - - /* Register with hwmon */ - data->hwmon_dev = hwmon_device_register(&data->pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - dev_err(&data->pdev->dev, "Unable to register hwmon " - "device for IPMI interface %d\n", - probe->interface); - res = PTR_ERR(data->hwmon_dev); - goto hwmon_reg_err; - } - - data->update = update_aem1_sensors; - data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL); - if (!data->rs_resp) { - res = -ENOMEM; - goto alloc_resp_err; - } - - /* Find sensors */ - res = aem1_find_sensors(data); - if (res) - goto sensor_err; - - /* Add to our list of AEM devices */ - list_add_tail(&data->list, &driver_data.aem_devices); - - dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n", - data->ver_major, data->ver_minor, - data->module_handle); - return 0; - -sensor_err: - kfree(data->rs_resp); -alloc_resp_err: - hwmon_device_unregister(data->hwmon_dev); -hwmon_reg_err: - ipmi_destroy_user(data->ipmi.user); -ipmi_err: - platform_set_drvdata(data->pdev, NULL); - platform_device_unregister(data->pdev); -dev_err: - ida_simple_remove(&aem_ida, data->id); -id_err: - kfree(data); - - return res; -} - -/* Find and initialize all AEM1 instances */ -static void aem_init_aem1(struct aem_ipmi_data *probe) -{ - int num, i, err; - - num = aem_find_aem1_count(probe); - for (i = 0; i < num; i++) { - err = aem_init_aem1_inst(probe, i); - if (err) { - dev_err(probe->bmc_device, - "Error %d initializing AEM1 0x%X\n", - err, i); - } - } -} - -/* Probe functions for AEM2 devices */ - -/* Retrieve version and module handle for an AEM2 instance */ -static int aem_find_aem2(struct aem_ipmi_data *data, - struct aem_find_instance_resp *fi_resp, - int instance_num) -{ - int res; - struct aem_find_instance_req fi_req; - - fi_req.id = system_x_id; - fi_req.instance_number = instance_num; - fi_req.module_type_id = cpu_to_be16(AEM_MODULE_TYPE_ID); - - data->tx_message.cmd = AEM_FW_INSTANCE_CMD; - data->tx_message.data = (char *)&fi_req; - data->tx_message.data_len = sizeof(fi_req); - - data->rx_msg_data = fi_resp; - data->rx_msg_len = sizeof(*fi_resp); - - aem_send_message(data); - - res = wait_for_completion_timeout(&data->read_complete, IPMI_TIMEOUT); - if (!res) - return -ETIMEDOUT; - - if (data->rx_result || data->rx_msg_len != sizeof(*fi_resp) || - memcmp(&fi_resp->id, &system_x_id, sizeof(system_x_id)) || - fi_resp->num_instances <= instance_num) - return -ENOENT; - - return 0; -} - -/* Find and initialize one AEM2 instance */ -static int aem_init_aem2_inst(struct aem_ipmi_data *probe, - struct aem_find_instance_resp *fi_resp) -{ - struct aem_data *data; - int i; - int res = -ENOMEM; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) - return res; - mutex_init(&data->lock); - - /* Copy instance data */ - data->ver_major = fi_resp->major; - data->ver_minor = fi_resp->minor; - data->module_handle = fi_resp->module_handle; - for (i = 0; i < AEM2_NUM_ENERGY_REGS; i++) - data->power_period[i] = AEM_DEFAULT_POWER_INTERVAL; - - /* Create sub-device for this fw instance */ - data->id = ida_simple_get(&aem_ida, 0, 0, GFP_KERNEL); - if (data->id < 0) - goto id_err; - - data->pdev = platform_device_alloc(DRVNAME, data->id); - if (!data->pdev) - goto dev_err; - data->pdev->dev.driver = &aem_driver.driver; - - res = platform_device_add(data->pdev); - if (res) - goto ipmi_err; - - platform_set_drvdata(data->pdev, data); - - /* Set up IPMI interface */ - res = aem_init_ipmi_data(&data->ipmi, probe->interface, - probe->bmc_device); - if (res) - goto ipmi_err; - - /* Register with hwmon */ - data->hwmon_dev = hwmon_device_register(&data->pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - dev_err(&data->pdev->dev, "Unable to register hwmon " - "device for IPMI interface %d\n", - probe->interface); - res = PTR_ERR(data->hwmon_dev); - goto hwmon_reg_err; - } - - data->update = update_aem2_sensors; - data->rs_resp = kzalloc(sizeof(*(data->rs_resp)) + 8, GFP_KERNEL); - if (!data->rs_resp) { - res = -ENOMEM; - goto alloc_resp_err; - } - - /* Find sensors */ - res = aem2_find_sensors(data); - if (res) - goto sensor_err; - - /* Add to our list of AEM devices */ - list_add_tail(&data->list, &driver_data.aem_devices); - - dev_info(data->ipmi.bmc_device, "Found AEM v%d.%d at 0x%X\n", - data->ver_major, data->ver_minor, - data->module_handle); - return 0; - -sensor_err: - kfree(data->rs_resp); -alloc_resp_err: - hwmon_device_unregister(data->hwmon_dev); -hwmon_reg_err: - ipmi_destroy_user(data->ipmi.user); -ipmi_err: - platform_set_drvdata(data->pdev, NULL); - platform_device_unregister(data->pdev); -dev_err: - ida_simple_remove(&aem_ida, data->id); -id_err: - kfree(data); - - return res; -} - -/* Find and initialize all AEM2 instances */ -static void aem_init_aem2(struct aem_ipmi_data *probe) -{ - struct aem_find_instance_resp fi_resp; - int err; - int i = 0; - - while (!aem_find_aem2(probe, &fi_resp, i)) { - if (fi_resp.major != 2) { - dev_err(probe->bmc_device, "Unknown AEM v%d; please " - "report this to the maintainer.\n", - fi_resp.major); - i++; - continue; - } - err = aem_init_aem2_inst(probe, &fi_resp); - if (err) { - dev_err(probe->bmc_device, - "Error %d initializing AEM2 0x%X\n", - err, fi_resp.module_handle); - } - i++; - } -} - -/* Probe a BMC for AEM firmware instances */ -static void aem_register_bmc(int iface, struct device *dev) -{ - struct aem_ipmi_data probe; - - if (aem_init_ipmi_data(&probe, iface, dev)) - return; - - /* Ignore probe errors; they won't cause problems */ - aem_init_aem1(&probe); - aem_init_aem2(&probe); - - ipmi_destroy_user(probe.user); -} - -/* Handle BMC deletion */ -static void aem_bmc_gone(int iface) -{ - struct aem_data *p1, *next1; - - list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) - if (p1->ipmi.interface == iface) - aem_delete(p1); -} - -/* sysfs support functions */ - -/* AEM device name */ -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct aem_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s%d\n", DRVNAME, data->ver_major); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -/* AEM device version */ -static ssize_t show_version(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct aem_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%d.%d\n", data->ver_major, data->ver_minor); -} -static SENSOR_DEVICE_ATTR(version, S_IRUGO, show_version, NULL, 0); - -/* Display power use */ -static ssize_t aem_show_power(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct aem_data *data = dev_get_drvdata(dev); - u64 before, after, delta, time; - signed long leftover; - struct timespec b, a; - - mutex_lock(&data->lock); - update_aem_energy_one(data, attr->index); - getnstimeofday(&b); - before = data->energy[attr->index]; - - leftover = schedule_timeout_interruptible( - msecs_to_jiffies(data->power_period[attr->index]) - ); - if (leftover) { - mutex_unlock(&data->lock); - return 0; - } - - update_aem_energy_one(data, attr->index); - getnstimeofday(&a); - after = data->energy[attr->index]; - mutex_unlock(&data->lock); - - time = timespec_to_ns(&a) - timespec_to_ns(&b); - delta = (after - before) * UJ_PER_MJ; - - return sprintf(buf, "%llu\n", - (unsigned long long)div64_u64(delta * NSEC_PER_SEC, time)); -} - -/* Display energy use */ -static ssize_t aem_show_energy(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct aem_data *a = dev_get_drvdata(dev); - mutex_lock(&a->lock); - update_aem_energy_one(a, attr->index); - mutex_unlock(&a->lock); - - return sprintf(buf, "%llu\n", - (unsigned long long)a->energy[attr->index] * 1000); -} - -/* Display power interval registers */ -static ssize_t aem_show_power_period(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct aem_data *a = dev_get_drvdata(dev); - a->update(a); - - return sprintf(buf, "%lu\n", a->power_period[attr->index]); -} - -/* Set power interval registers */ -static ssize_t aem_set_power_period(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct aem_data *a = dev_get_drvdata(dev); - unsigned long temp; - int res; - - res = kstrtoul(buf, 10, &temp); - if (res) - return res; - - if (temp < AEM_MIN_POWER_INTERVAL) - return -EINVAL; - - mutex_lock(&a->lock); - a->power_period[attr->index] = temp; - mutex_unlock(&a->lock); - - return count; -} - -/* Discover sensors on an AEM device */ -static int aem_register_sensors(struct aem_data *data, - struct aem_ro_sensor_template *ro, - struct aem_rw_sensor_template *rw) -{ - struct device *dev = &data->pdev->dev; - struct sensor_device_attribute *sensors = data->sensors; - int err; - - /* Set up read-only sensors */ - while (ro->label) { - sysfs_attr_init(&sensors->dev_attr.attr); - sensors->dev_attr.attr.name = ro->label; - sensors->dev_attr.attr.mode = S_IRUGO; - sensors->dev_attr.show = ro->show; - sensors->index = ro->index; - - err = device_create_file(dev, &sensors->dev_attr); - if (err) { - sensors->dev_attr.attr.name = NULL; - goto error; - } - sensors++; - ro++; - } - - /* Set up read-write sensors */ - while (rw->label) { - sysfs_attr_init(&sensors->dev_attr.attr); - sensors->dev_attr.attr.name = rw->label; - sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; - sensors->dev_attr.show = rw->show; - sensors->dev_attr.store = rw->set; - sensors->index = rw->index; - - err = device_create_file(dev, &sensors->dev_attr); - if (err) { - sensors->dev_attr.attr.name = NULL; - goto error; - } - sensors++; - rw++; - } - - err = device_create_file(dev, &sensor_dev_attr_name.dev_attr); - if (err) - goto error; - err = device_create_file(dev, &sensor_dev_attr_version.dev_attr); - return err; - -error: - aem_remove_sensors(data); - return err; -} - -/* sysfs support functions for AEM2 sensors */ - -/* Display temperature use */ -static ssize_t aem2_show_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct aem_data *a = dev_get_drvdata(dev); - a->update(a); - - return sprintf(buf, "%u\n", a->temp[attr->index] * 1000); -} - -/* Display power-capping registers */ -static ssize_t aem2_show_pcap_value(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct aem_data *a = dev_get_drvdata(dev); - a->update(a); - - return sprintf(buf, "%u\n", a->pcap[attr->index] * 100000); -} - -/* Remove sensors attached to an AEM device */ -static void aem_remove_sensors(struct aem_data *data) -{ - int i; - - for (i = 0; i < AEM_NUM_SENSORS; i++) { - if (!data->sensors[i].dev_attr.attr.name) - continue; - device_remove_file(&data->pdev->dev, - &data->sensors[i].dev_attr); - } - - device_remove_file(&data->pdev->dev, - &sensor_dev_attr_name.dev_attr); - device_remove_file(&data->pdev->dev, - &sensor_dev_attr_version.dev_attr); -} - -/* Sensor probe functions */ - -/* Description of AEM1 sensors */ -static struct aem_ro_sensor_template aem1_ro_sensors[] = { -{"energy1_input", aem_show_energy, 0}, -{"power1_average", aem_show_power, 0}, -{NULL, NULL, 0}, -}; - -static struct aem_rw_sensor_template aem1_rw_sensors[] = { -{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0}, -{NULL, NULL, NULL, 0}, -}; - -/* Description of AEM2 sensors */ -static struct aem_ro_sensor_template aem2_ro_sensors[] = { -{"energy1_input", aem_show_energy, 0}, -{"energy2_input", aem_show_energy, 1}, -{"power1_average", aem_show_power, 0}, -{"power2_average", aem_show_power, 1}, -{"temp1_input", aem2_show_temp, 0}, -{"temp2_input", aem2_show_temp, 1}, - -{"power4_average", aem2_show_pcap_value, POWER_CAP_MAX_HOTPLUG}, -{"power5_average", aem2_show_pcap_value, POWER_CAP_MAX}, -{"power6_average", aem2_show_pcap_value, POWER_CAP_MIN_WARNING}, -{"power7_average", aem2_show_pcap_value, POWER_CAP_MIN}, - -{"power3_average", aem2_show_pcap_value, POWER_AUX}, -{"power_cap", aem2_show_pcap_value, POWER_CAP}, -{NULL, NULL, 0}, -}; - -static struct aem_rw_sensor_template aem2_rw_sensors[] = { -{"power1_average_interval", aem_show_power_period, aem_set_power_period, 0}, -{"power2_average_interval", aem_show_power_period, aem_set_power_period, 1}, -{NULL, NULL, NULL, 0}, -}; - -/* Set up AEM1 sensor attrs */ -static int aem1_find_sensors(struct aem_data *data) -{ - return aem_register_sensors(data, aem1_ro_sensors, aem1_rw_sensors); -} - -/* Set up AEM2 sensor attrs */ -static int aem2_find_sensors(struct aem_data *data) -{ - return aem_register_sensors(data, aem2_ro_sensors, aem2_rw_sensors); -} - -/* Module init/exit routines */ - -static int __init aem_init(void) -{ - int res; - - res = driver_register(&aem_driver.driver); - if (res) { - pr_err("Can't register aem driver\n"); - return res; - } - - res = ipmi_smi_watcher_register(&driver_data.bmc_events); - if (res) - goto ipmi_reg_err; - return 0; - -ipmi_reg_err: - driver_unregister(&aem_driver.driver); - return res; - -} - -static void __exit aem_exit(void) -{ - struct aem_data *p1, *next1; - - ipmi_smi_watcher_unregister(&driver_data.bmc_events); - driver_unregister(&aem_driver.driver); - list_for_each_entry_safe(p1, next1, &driver_data.aem_devices, list) - aem_delete(p1); -} - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("IBM AEM power/temp/energy sensor driver"); -MODULE_LICENSE("GPL"); - -module_init(aem_init); -module_exit(aem_exit); - -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3350-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBM3850M2/x3950M2-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMBladeHC10-*"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ibmpex.c b/ANDROID_3.4.5/drivers/hwmon/ibmpex.c deleted file mode 100644 index 41dbf816..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ibmpex.c +++ /dev/null @@ -1,618 +0,0 @@ -/* - * A hwmon driver for the IBM PowerExecutive temperature/power sensors - * Copyright (C) 2007 IBM - * - * Author: Darrick J. Wong - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include - -#define REFRESH_INTERVAL (2 * HZ) -#define DRVNAME "ibmpex" - -#define PEX_GET_VERSION 1 -#define PEX_GET_SENSOR_COUNT 2 -#define PEX_GET_SENSOR_NAME 3 -#define PEX_RESET_HIGH_LOW 4 -#define PEX_GET_SENSOR_DATA 6 - -#define PEX_NET_FUNCTION 0x3A -#define PEX_COMMAND 0x3C - -static inline u16 extract_value(const char *data, int offset) -{ - return be16_to_cpup((__be16 *)&data[offset]); -} - -#define TEMP_SENSOR 1 -#define POWER_SENSOR 2 - -#define PEX_SENSOR_TYPE_LEN 3 -static u8 const power_sensor_sig[] = {0x70, 0x77, 0x72}; -static u8 const temp_sensor_sig[] = {0x74, 0x65, 0x6D}; - -#define PEX_MULT_LEN 2 -static u8 const watt_sensor_sig[] = {0x41, 0x43}; - -#define PEX_NUM_SENSOR_FUNCS 3 -static char const * const power_sensor_name_templates[] = { - "%s%d_average", - "%s%d_average_lowest", - "%s%d_average_highest" -}; -static char const * const temp_sensor_name_templates[] = { - "%s%d_input", - "%s%d_input_lowest", - "%s%d_input_highest" -}; - -static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data); -static void ibmpex_register_bmc(int iface, struct device *dev); -static void ibmpex_bmc_gone(int iface); - -struct ibmpex_sensor_data { - int in_use; - s16 values[PEX_NUM_SENSOR_FUNCS]; - int multiplier; - - struct sensor_device_attribute_2 attr[PEX_NUM_SENSOR_FUNCS]; -}; - -struct ibmpex_bmc_data { - struct list_head list; - struct device *hwmon_dev; - struct device *bmc_device; - struct mutex lock; - char valid; - unsigned long last_updated; /* In jiffies */ - - struct ipmi_addr address; - struct completion read_complete; - ipmi_user_t user; - int interface; - - struct kernel_ipmi_msg tx_message; - unsigned char tx_msg_data[IPMI_MAX_MSG_LENGTH]; - long tx_msgid; - - unsigned char rx_msg_data[IPMI_MAX_MSG_LENGTH]; - unsigned long rx_msg_len; - unsigned char rx_result; - int rx_recv_type; - - unsigned char sensor_major; - unsigned char sensor_minor; - - unsigned char num_sensors; - struct ibmpex_sensor_data *sensors; -}; - -struct ibmpex_driver_data { - struct list_head bmc_data; - struct ipmi_smi_watcher bmc_events; - struct ipmi_user_hndl ipmi_hndlrs; -}; - -static struct ibmpex_driver_data driver_data = { - .bmc_data = LIST_HEAD_INIT(driver_data.bmc_data), - .bmc_events = { - .owner = THIS_MODULE, - .new_smi = ibmpex_register_bmc, - .smi_gone = ibmpex_bmc_gone, - }, - .ipmi_hndlrs = { - .ipmi_recv_hndl = ibmpex_msg_handler, - }, -}; - -static int ibmpex_send_message(struct ibmpex_bmc_data *data) -{ - int err; - - err = ipmi_validate_addr(&data->address, sizeof(data->address)); - if (err) - goto out; - - data->tx_msgid++; - err = ipmi_request_settime(data->user, &data->address, data->tx_msgid, - &data->tx_message, data, 0, 0, 0); - if (err) - goto out1; - - return 0; -out1: - dev_err(data->bmc_device, "request_settime=%x\n", err); - return err; -out: - dev_err(data->bmc_device, "validate_addr=%x\n", err); - return err; -} - -static int ibmpex_ver_check(struct ibmpex_bmc_data *data) -{ - data->tx_msg_data[0] = PEX_GET_VERSION; - data->tx_message.data_len = 1; - ibmpex_send_message(data); - - wait_for_completion(&data->read_complete); - - if (data->rx_result || data->rx_msg_len != 6) - return -ENOENT; - - data->sensor_major = data->rx_msg_data[0]; - data->sensor_minor = data->rx_msg_data[1]; - - dev_info(data->bmc_device, "Found BMC with sensor interface " - "v%d.%d %d-%02d-%02d on interface %d\n", - data->sensor_major, - data->sensor_minor, - extract_value(data->rx_msg_data, 2), - data->rx_msg_data[4], - data->rx_msg_data[5], - data->interface); - - return 0; -} - -static int ibmpex_query_sensor_count(struct ibmpex_bmc_data *data) -{ - data->tx_msg_data[0] = PEX_GET_SENSOR_COUNT; - data->tx_message.data_len = 1; - ibmpex_send_message(data); - - wait_for_completion(&data->read_complete); - - if (data->rx_result || data->rx_msg_len != 1) - return -ENOENT; - - return data->rx_msg_data[0]; -} - -static int ibmpex_query_sensor_name(struct ibmpex_bmc_data *data, int sensor) -{ - data->tx_msg_data[0] = PEX_GET_SENSOR_NAME; - data->tx_msg_data[1] = sensor; - data->tx_message.data_len = 2; - ibmpex_send_message(data); - - wait_for_completion(&data->read_complete); - - if (data->rx_result || data->rx_msg_len < 1) - return -ENOENT; - - return 0; -} - -static int ibmpex_query_sensor_data(struct ibmpex_bmc_data *data, int sensor) -{ - data->tx_msg_data[0] = PEX_GET_SENSOR_DATA; - data->tx_msg_data[1] = sensor; - data->tx_message.data_len = 2; - ibmpex_send_message(data); - - wait_for_completion(&data->read_complete); - - if (data->rx_result || data->rx_msg_len < 26) { - dev_err(data->bmc_device, "Error reading sensor %d.\n", - sensor); - return -ENOENT; - } - - return 0; -} - -static int ibmpex_reset_high_low_data(struct ibmpex_bmc_data *data) -{ - data->tx_msg_data[0] = PEX_RESET_HIGH_LOW; - data->tx_message.data_len = 1; - ibmpex_send_message(data); - - wait_for_completion(&data->read_complete); - - return 0; -} - -static void ibmpex_update_device(struct ibmpex_bmc_data *data) -{ - int i, err; - - mutex_lock(&data->lock); - if (time_before(jiffies, data->last_updated + REFRESH_INTERVAL) && - data->valid) - goto out; - - for (i = 0; i < data->num_sensors; i++) { - if (!data->sensors[i].in_use) - continue; - err = ibmpex_query_sensor_data(data, i); - if (err) - continue; - data->sensors[i].values[0] = - extract_value(data->rx_msg_data, 16); - data->sensors[i].values[1] = - extract_value(data->rx_msg_data, 18); - data->sensors[i].values[2] = - extract_value(data->rx_msg_data, 20); - } - - data->last_updated = jiffies; - data->valid = 1; - -out: - mutex_unlock(&data->lock); -} - -static struct ibmpex_bmc_data *get_bmc_data(int iface) -{ - struct ibmpex_bmc_data *p, *next; - - list_for_each_entry_safe(p, next, &driver_data.bmc_data, list) - if (p->interface == iface) - return p; - - return NULL; -} - -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - return sprintf(buf, "%s\n", DRVNAME); -} -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -static ssize_t ibmpex_show_sensor(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct ibmpex_bmc_data *data = dev_get_drvdata(dev); - int mult = data->sensors[attr->index].multiplier; - ibmpex_update_device(data); - - return sprintf(buf, "%d\n", - data->sensors[attr->index].values[attr->nr] * mult); -} - -static ssize_t ibmpex_reset_high_low(struct device *dev, - struct device_attribute *devattr, - const char *buf, - size_t count) -{ - struct ibmpex_bmc_data *data = dev_get_drvdata(dev); - - ibmpex_reset_high_low_data(data); - - return count; -} - -static SENSOR_DEVICE_ATTR(reset_high_low, S_IWUSR, NULL, - ibmpex_reset_high_low, 0); - -static int is_power_sensor(const char *sensor_id, int len) -{ - if (len < PEX_SENSOR_TYPE_LEN) - return 0; - - if (!memcmp(sensor_id, power_sensor_sig, PEX_SENSOR_TYPE_LEN)) - return 1; - return 0; -} - -static int is_temp_sensor(const char *sensor_id, int len) -{ - if (len < PEX_SENSOR_TYPE_LEN) - return 0; - - if (!memcmp(sensor_id, temp_sensor_sig, PEX_SENSOR_TYPE_LEN)) - return 1; - return 0; -} - -static int power_sensor_multiplier(struct ibmpex_bmc_data *data, - const char *sensor_id, int len) -{ - int i; - - if (data->sensor_major == 2) - return 1000000; - - for (i = PEX_SENSOR_TYPE_LEN; i < len - 1; i++) - if (!memcmp(&sensor_id[i], watt_sensor_sig, PEX_MULT_LEN)) - return 1000000; - - return 100000; -} - -static int create_sensor(struct ibmpex_bmc_data *data, int type, - int counter, int sensor, int func) -{ - int err; - char *n; - - n = kmalloc(32, GFP_KERNEL); - if (!n) - return -ENOMEM; - - if (type == TEMP_SENSOR) - sprintf(n, temp_sensor_name_templates[func], "temp", counter); - else if (type == POWER_SENSOR) - sprintf(n, power_sensor_name_templates[func], "power", counter); - - sysfs_attr_init(&data->sensors[sensor].attr[func].dev_attr.attr); - data->sensors[sensor].attr[func].dev_attr.attr.name = n; - data->sensors[sensor].attr[func].dev_attr.attr.mode = S_IRUGO; - data->sensors[sensor].attr[func].dev_attr.show = ibmpex_show_sensor; - data->sensors[sensor].attr[func].index = sensor; - data->sensors[sensor].attr[func].nr = func; - - err = device_create_file(data->bmc_device, - &data->sensors[sensor].attr[func].dev_attr); - if (err) { - data->sensors[sensor].attr[func].dev_attr.attr.name = NULL; - kfree(n); - return err; - } - - return 0; -} - -static int ibmpex_find_sensors(struct ibmpex_bmc_data *data) -{ - int i, j, err; - int sensor_type; - int sensor_counter; - int num_power = 0; - int num_temp = 0; - - err = ibmpex_query_sensor_count(data); - if (err <= 0) - return -ENOENT; - data->num_sensors = err; - - data->sensors = kzalloc(data->num_sensors * sizeof(*data->sensors), - GFP_KERNEL); - if (!data->sensors) - return -ENOMEM; - - for (i = 0; i < data->num_sensors; i++) { - err = ibmpex_query_sensor_name(data, i); - if (err) - continue; - - if (is_power_sensor(data->rx_msg_data, data->rx_msg_len)) { - sensor_type = POWER_SENSOR; - num_power++; - sensor_counter = num_power; - data->sensors[i].multiplier = - power_sensor_multiplier(data, - data->rx_msg_data, - data->rx_msg_len); - } else if (is_temp_sensor(data->rx_msg_data, - data->rx_msg_len)) { - sensor_type = TEMP_SENSOR; - num_temp++; - sensor_counter = num_temp; - data->sensors[i].multiplier = 1000; - } else - continue; - - data->sensors[i].in_use = 1; - - /* Create attributes */ - for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) { - err = create_sensor(data, sensor_type, sensor_counter, - i, j); - if (err) - goto exit_remove; - } - } - - err = device_create_file(data->bmc_device, - &sensor_dev_attr_reset_high_low.dev_attr); - if (err) - goto exit_remove; - - err = device_create_file(data->bmc_device, - &sensor_dev_attr_name.dev_attr); - if (err) - goto exit_remove; - - return 0; - -exit_remove: - device_remove_file(data->bmc_device, - &sensor_dev_attr_reset_high_low.dev_attr); - device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr); - for (i = 0; i < data->num_sensors; i++) - for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) { - if (!data->sensors[i].attr[j].dev_attr.attr.name) - continue; - device_remove_file(data->bmc_device, - &data->sensors[i].attr[j].dev_attr); - kfree(data->sensors[i].attr[j].dev_attr.attr.name); - } - - kfree(data->sensors); - return err; -} - -static void ibmpex_register_bmc(int iface, struct device *dev) -{ - struct ibmpex_bmc_data *data; - int err; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - dev_err(dev, "Insufficient memory for BMC interface.\n"); - return; - } - - data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; - data->address.channel = IPMI_BMC_CHANNEL; - data->address.data[0] = 0; - data->interface = iface; - data->bmc_device = dev; - - /* Create IPMI messaging interface user */ - err = ipmi_create_user(data->interface, &driver_data.ipmi_hndlrs, - data, &data->user); - if (err < 0) { - dev_err(dev, "Unable to register user with IPMI " - "interface %d\n", data->interface); - goto out; - } - - mutex_init(&data->lock); - - /* Initialize message */ - data->tx_msgid = 0; - init_completion(&data->read_complete); - data->tx_message.netfn = PEX_NET_FUNCTION; - data->tx_message.cmd = PEX_COMMAND; - data->tx_message.data = data->tx_msg_data; - - /* Does this BMC support PowerExecutive? */ - err = ibmpex_ver_check(data); - if (err) - goto out_user; - - /* Register the BMC as a HWMON class device */ - data->hwmon_dev = hwmon_device_register(data->bmc_device); - - if (IS_ERR(data->hwmon_dev)) { - dev_err(data->bmc_device, "Unable to register hwmon " - "device for IPMI interface %d\n", - data->interface); - goto out_user; - } - - /* finally add the new bmc data to the bmc data list */ - dev_set_drvdata(dev, data); - list_add_tail(&data->list, &driver_data.bmc_data); - - /* Now go find all the sensors */ - err = ibmpex_find_sensors(data); - if (err) { - dev_err(data->bmc_device, "Error %d finding sensors\n", err); - goto out_register; - } - - return; - -out_register: - hwmon_device_unregister(data->hwmon_dev); -out_user: - ipmi_destroy_user(data->user); -out: - kfree(data); -} - -static void ibmpex_bmc_delete(struct ibmpex_bmc_data *data) -{ - int i, j; - - device_remove_file(data->bmc_device, - &sensor_dev_attr_reset_high_low.dev_attr); - device_remove_file(data->bmc_device, &sensor_dev_attr_name.dev_attr); - for (i = 0; i < data->num_sensors; i++) - for (j = 0; j < PEX_NUM_SENSOR_FUNCS; j++) { - if (!data->sensors[i].attr[j].dev_attr.attr.name) - continue; - device_remove_file(data->bmc_device, - &data->sensors[i].attr[j].dev_attr); - kfree(data->sensors[i].attr[j].dev_attr.attr.name); - } - - list_del(&data->list); - dev_set_drvdata(data->bmc_device, NULL); - hwmon_device_unregister(data->hwmon_dev); - ipmi_destroy_user(data->user); - kfree(data->sensors); - kfree(data); -} - -static void ibmpex_bmc_gone(int iface) -{ - struct ibmpex_bmc_data *data = get_bmc_data(iface); - - if (!data) - return; - - ibmpex_bmc_delete(data); -} - -static void ibmpex_msg_handler(struct ipmi_recv_msg *msg, void *user_msg_data) -{ - struct ibmpex_bmc_data *data = (struct ibmpex_bmc_data *)user_msg_data; - - if (msg->msgid != data->tx_msgid) { - dev_err(data->bmc_device, "Mismatch between received msgid " - "(%02x) and transmitted msgid (%02x)!\n", - (int)msg->msgid, - (int)data->tx_msgid); - ipmi_free_recv_msg(msg); - return; - } - - data->rx_recv_type = msg->recv_type; - if (msg->msg.data_len > 0) - data->rx_result = msg->msg.data[0]; - else - data->rx_result = IPMI_UNKNOWN_ERR_COMPLETION_CODE; - - if (msg->msg.data_len > 1) { - data->rx_msg_len = msg->msg.data_len - 1; - memcpy(data->rx_msg_data, msg->msg.data + 1, data->rx_msg_len); - } else - data->rx_msg_len = 0; - - ipmi_free_recv_msg(msg); - complete(&data->read_complete); -} - -static int __init ibmpex_init(void) -{ - return ipmi_smi_watcher_register(&driver_data.bmc_events); -} - -static void __exit ibmpex_exit(void) -{ - struct ibmpex_bmc_data *p, *next; - - ipmi_smi_watcher_unregister(&driver_data.bmc_events); - list_for_each_entry_safe(p, next, &driver_data.bmc_data, list) - ibmpex_bmc_delete(p); -} - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("IBM PowerExecutive power/temperature sensor driver"); -MODULE_LICENSE("GPL"); - -module_init(ibmpex_init); -module_exit(ibmpex_exit); - -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3350-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3550-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3650-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3655-*"); -MODULE_ALIAS("dmi:bvnIBM:*:pnIBMSystemx3755-*"); diff --git a/ANDROID_3.4.5/drivers/hwmon/it87.c b/ANDROID_3.4.5/drivers/hwmon/it87.c deleted file mode 100644 index 0b204e4c..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/it87.c +++ /dev/null @@ -1,2377 +0,0 @@ -/* - * it87.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring. - * - * The IT8705F is an LPC-based Super I/O part that contains UARTs, a - * parallel port, an IR port, a MIDI port, a floppy controller, etc., in - * addition to an Environment Controller (Enhanced Hardware Monitor and - * Fan Controller) - * - * This driver supports only the Environment Controller in the IT8705F and - * similar parts. The other devices are supported by different drivers. - * - * Supports: IT8705F Super I/O chip w/LPC interface - * IT8712F Super I/O chip w/LPC interface - * IT8716F Super I/O chip w/LPC interface - * IT8718F Super I/O chip w/LPC interface - * IT8720F Super I/O chip w/LPC interface - * IT8721F Super I/O chip w/LPC interface - * IT8726F Super I/O chip w/LPC interface - * IT8728F Super I/O chip w/LPC interface - * IT8758E Super I/O chip w/LPC interface - * Sis950 A clone of the IT8705F - * - * Copyright (C) 2001 Chris Gauthron - * Copyright (C) 2005-2010 Jean Delvare - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "it87" - -enum chips { it87, it8712, it8716, it8718, it8720, it8721, it8728 }; - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static struct platform_device *pdev; - -#define REG 0x2e /* The register to read/write */ -#define DEV 0x07 /* Register: Logical device select */ -#define VAL 0x2f /* The value to read/write */ -#define PME 0x04 /* The device with the fan registers in it */ - -/* The device with the IT8718F/IT8720F VID value in it */ -#define GPIO 0x07 - -#define DEVID 0x20 /* Register: Device ID */ -#define DEVREV 0x22 /* Register: Device Revision */ - -static inline int superio_inb(int reg) -{ - outb(reg, REG); - return inb(VAL); -} - -static inline void superio_outb(int reg, int val) -{ - outb(reg, REG); - outb(val, VAL); -} - -static int superio_inw(int reg) -{ - int val; - outb(reg++, REG); - val = inb(VAL) << 8; - outb(reg, REG); - val |= inb(VAL); - return val; -} - -static inline void superio_select(int ldn) -{ - outb(DEV, REG); - outb(ldn, VAL); -} - -static inline int superio_enter(void) -{ - /* - * Try to reserve REG and REG + 1 for exclusive access. - */ - if (!request_muxed_region(REG, 2, DRVNAME)) - return -EBUSY; - - outb(0x87, REG); - outb(0x01, REG); - outb(0x55, REG); - outb(0x55, REG); - return 0; -} - -static inline void superio_exit(void) -{ - outb(0x02, REG); - outb(0x02, VAL); - release_region(REG, 2); -} - -/* Logical device 4 registers */ -#define IT8712F_DEVID 0x8712 -#define IT8705F_DEVID 0x8705 -#define IT8716F_DEVID 0x8716 -#define IT8718F_DEVID 0x8718 -#define IT8720F_DEVID 0x8720 -#define IT8721F_DEVID 0x8721 -#define IT8726F_DEVID 0x8726 -#define IT8728F_DEVID 0x8728 -#define IT87_ACT_REG 0x30 -#define IT87_BASE_REG 0x60 - -/* Logical device 7 registers (IT8712F and later) */ -#define IT87_SIO_GPIO3_REG 0x27 -#define IT87_SIO_GPIO5_REG 0x29 -#define IT87_SIO_PINX2_REG 0x2c /* Pin selection */ -#define IT87_SIO_VID_REG 0xfc /* VID value */ -#define IT87_SIO_BEEP_PIN_REG 0xf6 /* Beep pin mapping */ - -/* Update battery voltage after every reading if true */ -static bool update_vbat; - -/* Not all BIOSes properly configure the PWM registers */ -static bool fix_pwm_polarity; - -/* Many IT87 constants specified below */ - -/* Length of ISA address segment */ -#define IT87_EXTENT 8 - -/* Length of ISA address segment for Environmental Controller */ -#define IT87_EC_EXTENT 2 - -/* Offset of EC registers from ISA base address */ -#define IT87_EC_OFFSET 5 - -/* Where are the ISA address/data registers relative to the EC base address */ -#define IT87_ADDR_REG_OFFSET 0 -#define IT87_DATA_REG_OFFSET 1 - -/*----- The IT87 registers -----*/ - -#define IT87_REG_CONFIG 0x00 - -#define IT87_REG_ALARM1 0x01 -#define IT87_REG_ALARM2 0x02 -#define IT87_REG_ALARM3 0x03 - -/* - * The IT8718F and IT8720F have the VID value in a different register, in - * Super-I/O configuration space. - */ -#define IT87_REG_VID 0x0a -/* - * The IT8705F and IT8712F earlier than revision 0x08 use register 0x0b - * for fan divisors. Later IT8712F revisions must use 16-bit tachometer - * mode. - */ -#define IT87_REG_FAN_DIV 0x0b -#define IT87_REG_FAN_16BIT 0x0c - -/* Monitors: 9 voltage (0 to 7, battery), 3 temp (1 to 3), 3 fan (1 to 3) */ - -static const u8 IT87_REG_FAN[] = { 0x0d, 0x0e, 0x0f, 0x80, 0x82 }; -static const u8 IT87_REG_FAN_MIN[] = { 0x10, 0x11, 0x12, 0x84, 0x86 }; -static const u8 IT87_REG_FANX[] = { 0x18, 0x19, 0x1a, 0x81, 0x83 }; -static const u8 IT87_REG_FANX_MIN[] = { 0x1b, 0x1c, 0x1d, 0x85, 0x87 }; -#define IT87_REG_FAN_MAIN_CTRL 0x13 -#define IT87_REG_FAN_CTL 0x14 -#define IT87_REG_PWM(nr) (0x15 + (nr)) -#define IT87_REG_PWM_DUTY(nr) (0x63 + (nr) * 8) - -#define IT87_REG_VIN(nr) (0x20 + (nr)) -#define IT87_REG_TEMP(nr) (0x29 + (nr)) - -#define IT87_REG_VIN_MAX(nr) (0x30 + (nr) * 2) -#define IT87_REG_VIN_MIN(nr) (0x31 + (nr) * 2) -#define IT87_REG_TEMP_HIGH(nr) (0x40 + (nr) * 2) -#define IT87_REG_TEMP_LOW(nr) (0x41 + (nr) * 2) - -#define IT87_REG_VIN_ENABLE 0x50 -#define IT87_REG_TEMP_ENABLE 0x51 -#define IT87_REG_BEEP_ENABLE 0x5c - -#define IT87_REG_CHIPID 0x58 - -#define IT87_REG_AUTO_TEMP(nr, i) (0x60 + (nr) * 8 + (i)) -#define IT87_REG_AUTO_PWM(nr, i) (0x65 + (nr) * 8 + (i)) - - -struct it87_sio_data { - enum chips type; - /* Values read from Super-I/O config space */ - u8 revision; - u8 vid_value; - u8 beep_pin; - u8 internal; /* Internal sensors can be labeled */ - /* Features skipped based on config or DMI */ - u8 skip_vid; - u8 skip_fan; - u8 skip_pwm; -}; - -/* - * For each registered chip, we need to keep some data in memory. - * The structure is dynamically allocated. - */ -struct it87_data { - struct device *hwmon_dev; - enum chips type; - u8 revision; - - unsigned short addr; - const char *name; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u16 in_scaled; /* Internal voltage sensors are scaled */ - u8 in[9]; /* Register value */ - u8 in_max[8]; /* Register value */ - u8 in_min[8]; /* Register value */ - u8 has_fan; /* Bitfield, fans enabled */ - u16 fan[5]; /* Register values, possibly combined */ - u16 fan_min[5]; /* Register values, possibly combined */ - s8 temp[3]; /* Register value */ - s8 temp_high[3]; /* Register value */ - s8 temp_low[3]; /* Register value */ - u8 sensor; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 vid; /* Register encoding, combined */ - u8 vrm; - u32 alarms; /* Register encoding, combined */ - u8 beeps; /* Register encoding */ - u8 fan_main_ctrl; /* Register value */ - u8 fan_ctl; /* Register value */ - - /* - * The following 3 arrays correspond to the same registers up to - * the IT8720F. The meaning of bits 6-0 depends on the value of bit - * 7, and we want to preserve settings on mode changes, so we have - * to track all values separately. - * Starting with the IT8721F, the manual PWM duty cycles are stored - * in separate registers (8-bit values), so the separate tracking - * is no longer needed, but it is still done to keep the driver - * simple. - */ - u8 pwm_ctrl[3]; /* Register value */ - u8 pwm_duty[3]; /* Manual PWM value set by user */ - u8 pwm_temp_map[3]; /* PWM to temp. chan. mapping (bits 1-0) */ - - /* Automatic fan speed control registers */ - u8 auto_pwm[3][4]; /* [nr][3] is hard-coded */ - s8 auto_temp[3][5]; /* [nr][0] is point1_temp_hyst */ -}; - -static inline int has_12mv_adc(const struct it87_data *data) -{ - /* - * IT8721F and later have a 12 mV ADC, also with internal scaling - * on selected inputs. - */ - return data->type == it8721 - || data->type == it8728; -} - -static inline int has_newer_autopwm(const struct it87_data *data) -{ - /* - * IT8721F and later have separate registers for the temperature - * mapping and the manual duty cycle. - */ - return data->type == it8721 - || data->type == it8728; -} - -static u8 in_to_reg(const struct it87_data *data, int nr, long val) -{ - long lsb; - - if (has_12mv_adc(data)) { - if (data->in_scaled & (1 << nr)) - lsb = 24; - else - lsb = 12; - } else - lsb = 16; - - val = DIV_ROUND_CLOSEST(val, lsb); - return SENSORS_LIMIT(val, 0, 255); -} - -static int in_from_reg(const struct it87_data *data, int nr, int val) -{ - if (has_12mv_adc(data)) { - if (data->in_scaled & (1 << nr)) - return val * 24; - else - return val * 12; - } else - return val * 16; -} - -static inline u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, - 254); -} - -static inline u16 FAN16_TO_REG(long rpm) -{ - if (rpm == 0) - return 0xffff; - return SENSORS_LIMIT((1350000 + rpm) / (rpm * 2), 1, 0xfffe); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : (val) == 255 ? 0 : \ - 1350000 / ((val) * (div))) -/* The divider is fixed to 2 in 16-bit mode */ -#define FAN16_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \ - 1350000 / ((val) * 2)) - -#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (((val) - 500) / 1000) : \ - ((val) + 500) / 1000), -128, 127)) -#define TEMP_FROM_REG(val) ((val) * 1000) - -static u8 pwm_to_reg(const struct it87_data *data, long val) -{ - if (has_newer_autopwm(data)) - return val; - else - return val >> 1; -} - -static int pwm_from_reg(const struct it87_data *data, u8 reg) -{ - if (has_newer_autopwm(data)) - return reg; - else - return (reg & 0x7f) << 1; -} - - -static int DIV_TO_REG(int val) -{ - int answer = 0; - while (answer < 7 && (val >>= 1)) - answer++; - return answer; -} -#define DIV_FROM_REG(val) (1 << (val)) - -static const unsigned int pwm_freq[8] = { - 48000000 / 128, - 24000000 / 128, - 12000000 / 128, - 8000000 / 128, - 6000000 / 128, - 3000000 / 128, - 1500000 / 128, - 750000 / 128, -}; - -static inline int has_16bit_fans(const struct it87_data *data) -{ - /* - * IT8705F Datasheet 0.4.1, 3h == Version G. - * IT8712F Datasheet 0.9.1, section 8.3.5 indicates 8h == Version J. - * These are the first revisions with 16-bit tachometer support. - */ - return (data->type == it87 && data->revision >= 0x03) - || (data->type == it8712 && data->revision >= 0x08) - || data->type == it8716 - || data->type == it8718 - || data->type == it8720 - || data->type == it8721 - || data->type == it8728; -} - -static inline int has_old_autopwm(const struct it87_data *data) -{ - /* - * The old automatic fan speed control interface is implemented - * by IT8705F chips up to revision F and IT8712F chips up to - * revision G. - */ - return (data->type == it87 && data->revision < 0x03) - || (data->type == it8712 && data->revision < 0x08); -} - -static int it87_probe(struct platform_device *pdev); -static int __devexit it87_remove(struct platform_device *pdev); - -static int it87_read_value(struct it87_data *data, u8 reg); -static void it87_write_value(struct it87_data *data, u8 reg, u8 value); -static struct it87_data *it87_update_device(struct device *dev); -static int it87_check_pwm(struct device *dev); -static void it87_init_device(struct platform_device *pdev); - - -static struct platform_driver it87_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = it87_probe, - .remove = __devexit_p(it87_remove), -}; - -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in[nr])); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_min[nr])); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", in_from_reg(data, nr, data->in_max[nr])); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->in_min[nr] = in_to_reg(data, nr, val); - it87_write_value(data, IT87_REG_VIN_MIN(nr), - data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->in_max[nr] = in_to_reg(data, nr, val); - it87_write_value(data, IT87_REG_VIN_MAX(nr), - data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_in_offset(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); - -#define limit_in_offset(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); - -show_in_offset(0); -limit_in_offset(0); -show_in_offset(1); -limit_in_offset(1); -show_in_offset(2); -limit_in_offset(2); -show_in_offset(3); -limit_in_offset(3); -show_in_offset(4); -limit_in_offset(4); -show_in_offset(5); -limit_in_offset(5); -show_in_offset(6); -limit_in_offset(6); -show_in_offset(7); -limit_in_offset(7); -show_in_offset(8); - -/* 3 temperatures */ -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); -} -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_high[nr])); -} -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_low[nr])); -} -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->temp_high[nr] = TEMP_TO_REG(val); - it87_write_value(data, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->temp_low[nr] = TEMP_TO_REG(val); - it87_write_value(data, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]); - mutex_unlock(&data->update_lock); - return count; -} -#define show_temp_offset(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, offset - 1); - -show_temp_offset(1); -show_temp_offset(2); -show_temp_offset(3); - -static ssize_t show_sensor(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); - u8 reg = data->sensor; /* In case value is updated while used */ - - if (reg & (1 << nr)) - return sprintf(buf, "3\n"); /* thermal diode */ - if (reg & (8 << nr)) - return sprintf(buf, "4\n"); /* thermistor */ - return sprintf(buf, "0\n"); /* disabled */ -} -static ssize_t set_sensor(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - u8 reg; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - reg = it87_read_value(data, IT87_REG_TEMP_ENABLE); - reg &= ~(1 << nr); - reg &= ~(8 << nr); - if (val == 2) { /* backwards compatibility */ - dev_warn(dev, "Sensor type 2 is deprecated, please use 4 " - "instead\n"); - val = 4; - } - /* 3 = thermal diode; 4 = thermistor; 0 = disabled */ - if (val == 3) - reg |= 1 << nr; - else if (val == 4) - reg |= 8 << nr; - else if (val != 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->sensor = reg; - it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor); - data->valid = 0; /* Force cache refresh */ - mutex_unlock(&data->update_lock); - return count; -} -#define show_sensor_offset(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ - show_sensor, set_sensor, offset - 1); - -show_sensor_offset(1); -show_sensor_offset(2); -show_sensor_offset(3); - -/* 3 Fans */ - -static int pwm_mode(const struct it87_data *data, int nr) -{ - int ctrl = data->fan_main_ctrl & (1 << nr); - - if (ctrl == 0) /* Full speed */ - return 0; - if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ - return 2; - else /* Manual mode */ - return 1; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", pwm_mode(data, nr)); -} -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", - pwm_from_reg(data, data->pwm_duty[nr])); -} -static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct it87_data *data = it87_update_device(dev); - int index = (data->fan_ctl >> 4) & 0x07; - - return sprintf(buf, "%u\n", pwm_freq[index]); -} -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - u8 reg; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - reg = it87_read_value(data, IT87_REG_FAN_DIV); - switch (nr) { - case 0: - data->fan_div[nr] = reg & 0x07; - break; - case 1: - data->fan_div[nr] = (reg >> 3) & 0x07; - break; - case 2: - data->fan_div[nr] = (reg & 0x40) ? 3 : 1; - break; - } - - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - unsigned long val; - int min; - u8 old; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - old = it87_read_value(data, IT87_REG_FAN_DIV); - - /* Save fan min limit */ - min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - - switch (nr) { - case 0: - case 1: - data->fan_div[nr] = DIV_TO_REG(val); - break; - case 2: - if (val < 8) - data->fan_div[nr] = 1; - else - data->fan_div[nr] = 3; - } - val = old & 0x80; - val |= (data->fan_div[0] & 0x07); - val |= (data->fan_div[1] & 0x07) << 3; - if (data->fan_div[2] == 3) - val |= 0x1 << 6; - it87_write_value(data, IT87_REG_FAN_DIV, val); - - /* Restore fan min limit */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - it87_write_value(data, IT87_REG_FAN_MIN[nr], data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - return count; -} - -/* Returns 0 if OK, -EINVAL otherwise */ -static int check_trip_points(struct device *dev, int nr) -{ - const struct it87_data *data = dev_get_drvdata(dev); - int i, err = 0; - - if (has_old_autopwm(data)) { - for (i = 0; i < 3; i++) { - if (data->auto_temp[nr][i] > data->auto_temp[nr][i + 1]) - err = -EINVAL; - } - for (i = 0; i < 2; i++) { - if (data->auto_pwm[nr][i] > data->auto_pwm[nr][i + 1]) - err = -EINVAL; - } - } - - if (err) { - dev_err(dev, "Inconsistent trip points, not switching to " - "automatic mode\n"); - dev_err(dev, "Adjust the trip points and try again\n"); - } - return err; -} - -static ssize_t set_pwm_enable(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 2) - return -EINVAL; - - /* Check trip points before switching to automatic mode */ - if (val == 2) { - if (check_trip_points(dev, nr) < 0) - return -EINVAL; - } - - mutex_lock(&data->update_lock); - - if (val == 0) { - int tmp; - /* make sure the fan is on when in on/off mode */ - tmp = it87_read_value(data, IT87_REG_FAN_CTL); - it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr)); - /* set on/off mode */ - data->fan_main_ctrl &= ~(1 << nr); - it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, - data->fan_main_ctrl); - } else { - if (val == 1) /* Manual mode */ - data->pwm_ctrl[nr] = has_newer_autopwm(data) ? - data->pwm_temp_map[nr] : - data->pwm_duty[nr]; - else /* Automatic mode */ - data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; - it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); - /* set SmartGuardian mode */ - data->fan_main_ctrl |= (1 << nr); - it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, - data->fan_main_ctrl); - } - - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255) - return -EINVAL; - - mutex_lock(&data->update_lock); - if (has_newer_autopwm(data)) { - /* - * If we are in automatic mode, the PWM duty cycle register - * is read-only so we can't write the value. - */ - if (data->pwm_ctrl[nr] & 0x80) { - mutex_unlock(&data->update_lock); - return -EBUSY; - } - data->pwm_duty[nr] = pwm_to_reg(data, val); - it87_write_value(data, IT87_REG_PWM_DUTY(nr), - data->pwm_duty[nr]); - } else { - data->pwm_duty[nr] = pwm_to_reg(data, val); - /* - * If we are in manual mode, write the duty cycle immediately; - * otherwise, just store it for later use. - */ - if (!(data->pwm_ctrl[nr] & 0x80)) { - data->pwm_ctrl[nr] = data->pwm_duty[nr]; - it87_write_value(data, IT87_REG_PWM(nr), - data->pwm_ctrl[nr]); - } - } - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_pwm_freq(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct it87_data *data = dev_get_drvdata(dev); - unsigned long val; - int i; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - /* Search for the nearest available frequency */ - for (i = 0; i < 7; i++) { - if (val > (pwm_freq[i] + pwm_freq[i+1]) / 2) - break; - } - - mutex_lock(&data->update_lock); - data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f; - data->fan_ctl |= i << 4; - it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl); - mutex_unlock(&data->update_lock); - - return count; -} -static ssize_t show_pwm_temp_map(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = it87_update_device(dev); - int map; - - if (data->pwm_temp_map[nr] < 3) - map = 1 << data->pwm_temp_map[nr]; - else - map = 0; /* Should never happen */ - return sprintf(buf, "%d\n", map); -} -static ssize_t set_pwm_temp_map(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - - struct it87_data *data = dev_get_drvdata(dev); - long val; - u8 reg; - - /* - * This check can go away if we ever support automatic fan speed - * control on newer chips. - */ - if (!has_old_autopwm(data)) { - dev_notice(dev, "Mapping change disabled for safety reasons\n"); - return -EINVAL; - } - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - switch (val) { - case (1 << 0): - reg = 0x00; - break; - case (1 << 1): - reg = 0x01; - break; - case (1 << 2): - reg = 0x02; - break; - default: - return -EINVAL; - } - - mutex_lock(&data->update_lock); - data->pwm_temp_map[nr] = reg; - /* - * If we are in automatic mode, write the temp mapping immediately; - * otherwise, just store it for later use. - */ - if (data->pwm_ctrl[nr] & 0x80) { - data->pwm_ctrl[nr] = 0x80 | data->pwm_temp_map[nr]; - it87_write_value(data, IT87_REG_PWM(nr), data->pwm_ctrl[nr]); - } - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_auto_pwm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct it87_data *data = it87_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int point = sensor_attr->index; - - return sprintf(buf, "%d\n", - pwm_from_reg(data, data->auto_pwm[nr][point])); -} - -static ssize_t set_auto_pwm(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct it87_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int point = sensor_attr->index; - long val; - - if (kstrtol(buf, 10, &val) < 0 || val < 0 || val > 255) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->auto_pwm[nr][point] = pwm_to_reg(data, val); - it87_write_value(data, IT87_REG_AUTO_PWM(nr, point), - data->auto_pwm[nr][point]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_auto_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct it87_data *data = it87_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int point = sensor_attr->index; - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->auto_temp[nr][point])); -} - -static ssize_t set_auto_temp(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct it87_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int point = sensor_attr->index; - long val; - - if (kstrtol(buf, 10, &val) < 0 || val < -128000 || val > 127000) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->auto_temp[nr][point] = TEMP_TO_REG(val); - it87_write_value(data, IT87_REG_AUTO_TEMP(nr, point), - data->auto_temp[nr][point]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1); - -show_fan_offset(1); -show_fan_offset(2); -show_fan_offset(3); - -#define show_pwm_offset(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ - show_pwm_enable, set_pwm_enable, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, offset - 1); \ -static DEVICE_ATTR(pwm##offset##_freq, \ - (offset == 1 ? S_IRUGO | S_IWUSR : S_IRUGO), \ - show_pwm_freq, (offset == 1 ? set_pwm_freq : NULL)); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels_temp, \ - S_IRUGO | S_IWUSR, show_pwm_temp_map, set_pwm_temp_map, \ - offset - 1); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_pwm, \ - S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ - offset - 1, 0); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_pwm, \ - S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ - offset - 1, 1); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_pwm, \ - S_IRUGO | S_IWUSR, show_auto_pwm, set_auto_pwm, \ - offset - 1, 2); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_pwm, \ - S_IRUGO, show_auto_pwm, NULL, offset - 1, 3); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp, \ - S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ - offset - 1, 1); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point1_temp_hyst, \ - S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ - offset - 1, 0); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point2_temp, \ - S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ - offset - 1, 2); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point3_temp, \ - S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ - offset - 1, 3); \ -static SENSOR_DEVICE_ATTR_2(pwm##offset##_auto_point4_temp, \ - S_IRUGO | S_IWUSR, show_auto_temp, set_auto_temp, \ - offset - 1, 4); - -show_pwm_offset(1); -show_pwm_offset(2); -show_pwm_offset(3); - -/* A different set of callbacks for 16-bit fans */ -static ssize_t show_fan16(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan[nr])); -} - -static ssize_t show_fan16_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%d\n", FAN16_FROM_REG(data->fan_min[nr])); -} - -static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct it87_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN16_TO_REG(val); - it87_write_value(data, IT87_REG_FAN_MIN[nr], - data->fan_min[nr] & 0xff); - it87_write_value(data, IT87_REG_FANX_MIN[nr], - data->fan_min[nr] >> 8); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * We want to use the same sysfs file names as 8-bit fans, but we need - * different variable names, so we have to use SENSOR_ATTR instead of - * SENSOR_DEVICE_ATTR. - */ -#define show_fan16_offset(offset) \ -static struct sensor_device_attribute sensor_dev_attr_fan##offset##_input16 \ - = SENSOR_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan16, NULL, offset - 1); \ -static struct sensor_device_attribute sensor_dev_attr_fan##offset##_min16 \ - = SENSOR_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan16_min, set_fan16_min, offset - 1) - -show_fan16_offset(1); -show_fan16_offset(2); -show_fan16_offset(3); -show_fan16_offset(4); -show_fan16_offset(5); - -/* Alarms */ -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -static ssize_t clear_intrusion(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) -{ - struct it87_data *data = dev_get_drvdata(dev); - long val; - int config; - - if (kstrtol(buf, 10, &val) < 0 || val != 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - config = it87_read_value(data, IT87_REG_CONFIG); - if (config < 0) { - count = config; - } else { - config |= 1 << 5; - it87_write_value(data, IT87_REG_CONFIG, config); - /* Invalidate cache to force re-read */ - data->valid = 0; - } - mutex_unlock(&data->update_lock); - - return count; -} - -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 14); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 15); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 16); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 17); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 18); -static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, - show_alarm, clear_intrusion, 4); - -static ssize_t show_beep(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%u\n", (data->beeps >> bitnr) & 1); -} -static ssize_t set_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct it87_data *data = dev_get_drvdata(dev); - long val; - - if (kstrtol(buf, 10, &val) < 0 - || (val != 0 && val != 1)) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); - if (val) - data->beeps |= (1 << bitnr); - else - data->beeps &= ~(1 << bitnr); - it87_write_value(data, IT87_REG_BEEP_ENABLE, data->beeps); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, - show_beep, set_beep, 1); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO, show_beep, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO, show_beep, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO, show_beep, NULL, 1); -static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO, show_beep, NULL, 1); -static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO, show_beep, NULL, 1); -static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO, show_beep, NULL, 1); -static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO, show_beep, NULL, 1); -/* fanX_beep writability is set later */ -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(fan4_beep, S_IRUGO, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(fan5_beep, S_IRUGO, show_beep, set_beep, 0); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, - show_beep, set_beep, 2); -static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO, show_beep, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, show_beep, NULL, 2); - -static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct it87_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", data->vrm); -} -static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct it87_data *data = dev_get_drvdata(dev); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - data->vrm = val; - - return count; -} -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); - -static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct it87_data *data = it87_update_device(dev); - return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); - -static ssize_t show_label(struct device *dev, struct device_attribute *attr, - char *buf) -{ - static const char * const labels[] = { - "+5V", - "5VSB", - "Vbat", - }; - static const char * const labels_it8721[] = { - "+3.3V", - "3VSB", - "Vbat", - }; - struct it87_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%s\n", has_12mv_adc(data) ? labels_it8721[nr] - : labels[nr]); -} -static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_label, NULL, 0); -static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, show_label, NULL, 1); -static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, show_label, NULL, 2); - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct it87_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *it87_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp1_type.dev_attr.attr, - &sensor_dev_attr_temp2_type.dev_attr.attr, - &sensor_dev_attr_temp3_type.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - - &dev_attr_alarms.attr, - &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group it87_group = { - .attrs = it87_attributes, -}; - -static struct attribute *it87_attributes_beep[] = { - &sensor_dev_attr_in0_beep.dev_attr.attr, - &sensor_dev_attr_in1_beep.dev_attr.attr, - &sensor_dev_attr_in2_beep.dev_attr.attr, - &sensor_dev_attr_in3_beep.dev_attr.attr, - &sensor_dev_attr_in4_beep.dev_attr.attr, - &sensor_dev_attr_in5_beep.dev_attr.attr, - &sensor_dev_attr_in6_beep.dev_attr.attr, - &sensor_dev_attr_in7_beep.dev_attr.attr, - - &sensor_dev_attr_temp1_beep.dev_attr.attr, - &sensor_dev_attr_temp2_beep.dev_attr.attr, - &sensor_dev_attr_temp3_beep.dev_attr.attr, - NULL -}; - -static const struct attribute_group it87_group_beep = { - .attrs = it87_attributes_beep, -}; - -static struct attribute *it87_attributes_fan16[5][3+1] = { { - &sensor_dev_attr_fan1_input16.dev_attr.attr, - &sensor_dev_attr_fan1_min16.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan2_input16.dev_attr.attr, - &sensor_dev_attr_fan2_min16.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan3_input16.dev_attr.attr, - &sensor_dev_attr_fan3_min16.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan4_input16.dev_attr.attr, - &sensor_dev_attr_fan4_min16.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan5_input16.dev_attr.attr, - &sensor_dev_attr_fan5_min16.dev_attr.attr, - &sensor_dev_attr_fan5_alarm.dev_attr.attr, - NULL -} }; - -static const struct attribute_group it87_group_fan16[5] = { - { .attrs = it87_attributes_fan16[0] }, - { .attrs = it87_attributes_fan16[1] }, - { .attrs = it87_attributes_fan16[2] }, - { .attrs = it87_attributes_fan16[3] }, - { .attrs = it87_attributes_fan16[4] }, -}; - -static struct attribute *it87_attributes_fan[3][4+1] = { { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - NULL -} }; - -static const struct attribute_group it87_group_fan[3] = { - { .attrs = it87_attributes_fan[0] }, - { .attrs = it87_attributes_fan[1] }, - { .attrs = it87_attributes_fan[2] }, -}; - -static const struct attribute_group * -it87_get_fan_group(const struct it87_data *data) -{ - return has_16bit_fans(data) ? it87_group_fan16 : it87_group_fan; -} - -static struct attribute *it87_attributes_pwm[3][4+1] = { { - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &dev_attr_pwm1_freq.attr, - &sensor_dev_attr_pwm1_auto_channels_temp.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &dev_attr_pwm2_freq.attr, - &sensor_dev_attr_pwm2_auto_channels_temp.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &dev_attr_pwm3_freq.attr, - &sensor_dev_attr_pwm3_auto_channels_temp.dev_attr.attr, - NULL -} }; - -static const struct attribute_group it87_group_pwm[3] = { - { .attrs = it87_attributes_pwm[0] }, - { .attrs = it87_attributes_pwm[1] }, - { .attrs = it87_attributes_pwm[2] }, -}; - -static struct attribute *it87_attributes_autopwm[3][9+1] = { { - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_pwm2_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point3_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point4_pwm.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_point4_temp.dev_attr.attr, - NULL -}, { - &sensor_dev_attr_pwm3_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point3_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point4_pwm.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_point4_temp.dev_attr.attr, - NULL -} }; - -static const struct attribute_group it87_group_autopwm[3] = { - { .attrs = it87_attributes_autopwm[0] }, - { .attrs = it87_attributes_autopwm[1] }, - { .attrs = it87_attributes_autopwm[2] }, -}; - -static struct attribute *it87_attributes_fan_beep[] = { - &sensor_dev_attr_fan1_beep.dev_attr.attr, - &sensor_dev_attr_fan2_beep.dev_attr.attr, - &sensor_dev_attr_fan3_beep.dev_attr.attr, - &sensor_dev_attr_fan4_beep.dev_attr.attr, - &sensor_dev_attr_fan5_beep.dev_attr.attr, -}; - -static struct attribute *it87_attributes_vid[] = { - &dev_attr_vrm.attr, - &dev_attr_cpu0_vid.attr, - NULL -}; - -static const struct attribute_group it87_group_vid = { - .attrs = it87_attributes_vid, -}; - -static struct attribute *it87_attributes_label[] = { - &sensor_dev_attr_in3_label.dev_attr.attr, - &sensor_dev_attr_in7_label.dev_attr.attr, - &sensor_dev_attr_in8_label.dev_attr.attr, - NULL -}; - -static const struct attribute_group it87_group_label = { - .attrs = it87_attributes_label, -}; - -/* SuperIO detection - will change isa_address if a chip is found */ -static int __init it87_find(unsigned short *address, - struct it87_sio_data *sio_data) -{ - int err; - u16 chip_type; - const char *board_vendor, *board_name; - - err = superio_enter(); - if (err) - return err; - - err = -ENODEV; - chip_type = force_id ? force_id : superio_inw(DEVID); - - switch (chip_type) { - case IT8705F_DEVID: - sio_data->type = it87; - break; - case IT8712F_DEVID: - sio_data->type = it8712; - break; - case IT8716F_DEVID: - case IT8726F_DEVID: - sio_data->type = it8716; - break; - case IT8718F_DEVID: - sio_data->type = it8718; - break; - case IT8720F_DEVID: - sio_data->type = it8720; - break; - case IT8721F_DEVID: - sio_data->type = it8721; - break; - case IT8728F_DEVID: - sio_data->type = it8728; - break; - case 0xffff: /* No device at all */ - goto exit; - default: - pr_debug("Unsupported chip (DEVID=0x%x)\n", chip_type); - goto exit; - } - - superio_select(PME); - if (!(superio_inb(IT87_ACT_REG) & 0x01)) { - pr_info("Device not activated, skipping\n"); - goto exit; - } - - *address = superio_inw(IT87_BASE_REG) & ~(IT87_EXTENT - 1); - if (*address == 0) { - pr_info("Base address not set, skipping\n"); - goto exit; - } - - err = 0; - sio_data->revision = superio_inb(DEVREV) & 0x0f; - pr_info("Found IT%04xF chip at 0x%x, revision %d\n", - chip_type, *address, sio_data->revision); - - /* in8 (Vbat) is always internal */ - sio_data->internal = (1 << 2); - - /* Read GPIO config and VID value from LDN 7 (GPIO) */ - if (sio_data->type == it87) { - /* The IT8705F doesn't have VID pins at all */ - sio_data->skip_vid = 1; - - /* The IT8705F has a different LD number for GPIO */ - superio_select(5); - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; - } else { - int reg; - - superio_select(GPIO); - - reg = superio_inb(IT87_SIO_GPIO3_REG); - if (sio_data->type == it8721 || sio_data->type == it8728) { - /* - * The IT8721F/IT8758E doesn't have VID pins at all, - * not sure about the IT8728F. - */ - sio_data->skip_vid = 1; - } else { - /* We need at least 4 VID pins */ - if (reg & 0x0f) { - pr_info("VID is disabled (pins used for GPIO)\n"); - sio_data->skip_vid = 1; - } - } - - /* Check if fan3 is there or not */ - if (reg & (1 << 6)) - sio_data->skip_pwm |= (1 << 2); - if (reg & (1 << 7)) - sio_data->skip_fan |= (1 << 2); - - /* Check if fan2 is there or not */ - reg = superio_inb(IT87_SIO_GPIO5_REG); - if (reg & (1 << 1)) - sio_data->skip_pwm |= (1 << 1); - if (reg & (1 << 2)) - sio_data->skip_fan |= (1 << 1); - - if ((sio_data->type == it8718 || sio_data->type == it8720) - && !(sio_data->skip_vid)) - sio_data->vid_value = superio_inb(IT87_SIO_VID_REG); - - reg = superio_inb(IT87_SIO_PINX2_REG); - /* - * The IT8720F has no VIN7 pin, so VCCH should always be - * routed internally to VIN7 with an internal divider. - * Curiously, there still is a configuration bit to control - * this, which means it can be set incorrectly. And even - * more curiously, many boards out there are improperly - * configured, even though the IT8720F datasheet claims - * that the internal routing of VCCH to VIN7 is the default - * setting. So we force the internal routing in this case. - */ - if (sio_data->type == it8720 && !(reg & (1 << 1))) { - reg |= (1 << 1); - superio_outb(IT87_SIO_PINX2_REG, reg); - pr_notice("Routing internal VCCH to in7\n"); - } - if (reg & (1 << 0)) - sio_data->internal |= (1 << 0); - if ((reg & (1 << 1)) || sio_data->type == it8721 || - sio_data->type == it8728) - sio_data->internal |= (1 << 1); - - sio_data->beep_pin = superio_inb(IT87_SIO_BEEP_PIN_REG) & 0x3f; - } - if (sio_data->beep_pin) - pr_info("Beeping is supported\n"); - - /* Disable specific features based on DMI strings */ - board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR); - board_name = dmi_get_system_info(DMI_BOARD_NAME); - if (board_vendor && board_name) { - if (strcmp(board_vendor, "nVIDIA") == 0 - && strcmp(board_name, "FN68PT") == 0) { - /* - * On the Shuttle SN68PT, FAN_CTL2 is apparently not - * connected to a fan, but to something else. One user - * has reported instant system power-off when changing - * the PWM2 duty cycle, so we disable it. - * I use the board name string as the trigger in case - * the same board is ever used in other systems. - */ - pr_info("Disabling pwm2 due to hardware constraints\n"); - sio_data->skip_pwm = (1 << 1); - } - } - -exit: - superio_exit(); - return err; -} - -static void it87_remove_files(struct device *dev) -{ - struct it87_data *data = platform_get_drvdata(pdev); - struct it87_sio_data *sio_data = dev->platform_data; - const struct attribute_group *fan_group = it87_get_fan_group(data); - int i; - - sysfs_remove_group(&dev->kobj, &it87_group); - if (sio_data->beep_pin) - sysfs_remove_group(&dev->kobj, &it87_group_beep); - for (i = 0; i < 5; i++) { - if (!(data->has_fan & (1 << i))) - continue; - sysfs_remove_group(&dev->kobj, &fan_group[i]); - if (sio_data->beep_pin) - sysfs_remove_file(&dev->kobj, - it87_attributes_fan_beep[i]); - } - for (i = 0; i < 3; i++) { - if (sio_data->skip_pwm & (1 << 0)) - continue; - sysfs_remove_group(&dev->kobj, &it87_group_pwm[i]); - if (has_old_autopwm(data)) - sysfs_remove_group(&dev->kobj, - &it87_group_autopwm[i]); - } - if (!sio_data->skip_vid) - sysfs_remove_group(&dev->kobj, &it87_group_vid); - sysfs_remove_group(&dev->kobj, &it87_group_label); -} - -static int __devinit it87_probe(struct platform_device *pdev) -{ - struct it87_data *data; - struct resource *res; - struct device *dev = &pdev->dev; - struct it87_sio_data *sio_data = dev->platform_data; - const struct attribute_group *fan_group; - int err = 0, i; - int enable_pwm_interface; - int fan_beep_need_rw; - static const char * const names[] = { - "it87", - "it8712", - "it8716", - "it8718", - "it8720", - "it8721", - "it8728", - }; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, IT87_EC_EXTENT, DRVNAME)) { - dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, - (unsigned long)(res->start + IT87_EC_EXTENT - 1)); - err = -EBUSY; - goto ERROR0; - } - - data = kzalloc(sizeof(struct it87_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto ERROR1; - } - - data->addr = res->start; - data->type = sio_data->type; - data->revision = sio_data->revision; - data->name = names[sio_data->type]; - - /* Now, we do the remaining detection. */ - if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80) - || it87_read_value(data, IT87_REG_CHIPID) != 0x90) { - err = -ENODEV; - goto ERROR2; - } - - platform_set_drvdata(pdev, data); - - mutex_init(&data->update_lock); - - /* Check PWM configuration */ - enable_pwm_interface = it87_check_pwm(dev); - - /* Starting with IT8721F, we handle scaling of internal voltages */ - if (has_12mv_adc(data)) { - if (sio_data->internal & (1 << 0)) - data->in_scaled |= (1 << 3); /* in3 is AVCC */ - if (sio_data->internal & (1 << 1)) - data->in_scaled |= (1 << 7); /* in7 is VSB */ - if (sio_data->internal & (1 << 2)) - data->in_scaled |= (1 << 8); /* in8 is Vbat */ - } - - /* Initialize the IT87 chip */ - it87_init_device(pdev); - - /* Register sysfs hooks */ - err = sysfs_create_group(&dev->kobj, &it87_group); - if (err) - goto ERROR2; - - if (sio_data->beep_pin) { - err = sysfs_create_group(&dev->kobj, &it87_group_beep); - if (err) - goto ERROR4; - } - - /* Do not create fan files for disabled fans */ - fan_group = it87_get_fan_group(data); - fan_beep_need_rw = 1; - for (i = 0; i < 5; i++) { - if (!(data->has_fan & (1 << i))) - continue; - err = sysfs_create_group(&dev->kobj, &fan_group[i]); - if (err) - goto ERROR4; - - if (sio_data->beep_pin) { - err = sysfs_create_file(&dev->kobj, - it87_attributes_fan_beep[i]); - if (err) - goto ERROR4; - if (!fan_beep_need_rw) - continue; - - /* - * As we have a single beep enable bit for all fans, - * only the first enabled fan has a writable attribute - * for it. - */ - if (sysfs_chmod_file(&dev->kobj, - it87_attributes_fan_beep[i], - S_IRUGO | S_IWUSR)) - dev_dbg(dev, "chmod +w fan%d_beep failed\n", - i + 1); - fan_beep_need_rw = 0; - } - } - - if (enable_pwm_interface) { - for (i = 0; i < 3; i++) { - if (sio_data->skip_pwm & (1 << i)) - continue; - err = sysfs_create_group(&dev->kobj, - &it87_group_pwm[i]); - if (err) - goto ERROR4; - - if (!has_old_autopwm(data)) - continue; - err = sysfs_create_group(&dev->kobj, - &it87_group_autopwm[i]); - if (err) - goto ERROR4; - } - } - - if (!sio_data->skip_vid) { - data->vrm = vid_which_vrm(); - /* VID reading from Super-I/O config space if available */ - data->vid = sio_data->vid_value; - err = sysfs_create_group(&dev->kobj, &it87_group_vid); - if (err) - goto ERROR4; - } - - /* Export labels for internal sensors */ - for (i = 0; i < 3; i++) { - if (!(sio_data->internal & (1 << i))) - continue; - err = sysfs_create_file(&dev->kobj, - it87_attributes_label[i]); - if (err) - goto ERROR4; - } - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto ERROR4; - } - - return 0; - -ERROR4: - it87_remove_files(dev); -ERROR2: - platform_set_drvdata(pdev, NULL); - kfree(data); -ERROR1: - release_region(res->start, IT87_EC_EXTENT); -ERROR0: - return err; -} - -static int __devexit it87_remove(struct platform_device *pdev) -{ - struct it87_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - it87_remove_files(&pdev->dev); - - release_region(data->addr, IT87_EC_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -/* - * Must be called with data->update_lock held, except during initialization. - * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, - * would slow down the IT87 access and should not be necessary. - */ -static int it87_read_value(struct it87_data *data, u8 reg) -{ - outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); - return inb_p(data->addr + IT87_DATA_REG_OFFSET); -} - -/* - * Must be called with data->update_lock held, except during initialization. - * We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks, - * would slow down the IT87 access and should not be necessary. - */ -static void it87_write_value(struct it87_data *data, u8 reg, u8 value) -{ - outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET); - outb_p(value, data->addr + IT87_DATA_REG_OFFSET); -} - -/* Return 1 if and only if the PWM interface is safe to use */ -static int __devinit it87_check_pwm(struct device *dev) -{ - struct it87_data *data = dev_get_drvdata(dev); - /* - * Some BIOSes fail to correctly configure the IT87 fans. All fans off - * and polarity set to active low is sign that this is the case so we - * disable pwm control to protect the user. - */ - int tmp = it87_read_value(data, IT87_REG_FAN_CTL); - if ((tmp & 0x87) == 0) { - if (fix_pwm_polarity) { - /* - * The user asks us to attempt a chip reconfiguration. - * This means switching to active high polarity and - * inverting all fan speed values. - */ - int i; - u8 pwm[3]; - - for (i = 0; i < 3; i++) - pwm[i] = it87_read_value(data, - IT87_REG_PWM(i)); - - /* - * If any fan is in automatic pwm mode, the polarity - * might be correct, as suspicious as it seems, so we - * better don't change anything (but still disable the - * PWM interface). - */ - if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) { - dev_info(dev, "Reconfiguring PWM to " - "active high polarity\n"); - it87_write_value(data, IT87_REG_FAN_CTL, - tmp | 0x87); - for (i = 0; i < 3; i++) - it87_write_value(data, - IT87_REG_PWM(i), - 0x7f & ~pwm[i]); - return 1; - } - - dev_info(dev, "PWM configuration is " - "too broken to be fixed\n"); - } - - dev_info(dev, "Detected broken BIOS " - "defaults, disabling PWM interface\n"); - return 0; - } else if (fix_pwm_polarity) { - dev_info(dev, "PWM configuration looks " - "sane, won't touch\n"); - } - - return 1; -} - -/* Called when we have found a new IT87. */ -static void __devinit it87_init_device(struct platform_device *pdev) -{ - struct it87_sio_data *sio_data = pdev->dev.platform_data; - struct it87_data *data = platform_get_drvdata(pdev); - int tmp, i; - u8 mask; - - /* - * For each PWM channel: - * - If it is in automatic mode, setting to manual mode should set - * the fan to full speed by default. - * - If it is in manual mode, we need a mapping to temperature - * channels to use when later setting to automatic mode later. - * Use a 1:1 mapping by default (we are clueless.) - * In both cases, the value can (and should) be changed by the user - * prior to switching to a different mode. - * Note that this is no longer needed for the IT8721F and later, as - * these have separate registers for the temperature mapping and the - * manual duty cycle. - */ - for (i = 0; i < 3; i++) { - data->pwm_temp_map[i] = i; - data->pwm_duty[i] = 0x7f; /* Full speed */ - data->auto_pwm[i][3] = 0x7f; /* Full speed, hard-coded */ - } - - /* - * Some chips seem to have default value 0xff for all limit - * registers. For low voltage limits it makes no sense and triggers - * alarms, so change to 0 instead. For high temperature limits, it - * means -1 degree C, which surprisingly doesn't trigger an alarm, - * but is still confusing, so change to 127 degrees C. - */ - for (i = 0; i < 8; i++) { - tmp = it87_read_value(data, IT87_REG_VIN_MIN(i)); - if (tmp == 0xff) - it87_write_value(data, IT87_REG_VIN_MIN(i), 0); - } - for (i = 0; i < 3; i++) { - tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i)); - if (tmp == 0xff) - it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127); - } - - /* - * Temperature channels are not forcibly enabled, as they can be - * set to two different sensor types and we can't guess which one - * is correct for a given system. These channels can be enabled at - * run-time through the temp{1-3}_type sysfs accessors if needed. - */ - - /* Check if voltage monitors are reset manually or by some reason */ - tmp = it87_read_value(data, IT87_REG_VIN_ENABLE); - if ((tmp & 0xff) == 0) { - /* Enable all voltage monitors */ - it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff); - } - - /* Check if tachometers are reset manually or by some reason */ - mask = 0x70 & ~(sio_data->skip_fan << 4); - data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL); - if ((data->fan_main_ctrl & mask) == 0) { - /* Enable all fan tachometers */ - data->fan_main_ctrl |= mask; - it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, - data->fan_main_ctrl); - } - data->has_fan = (data->fan_main_ctrl >> 4) & 0x07; - - /* Set tachometers to 16-bit mode if needed */ - if (has_16bit_fans(data)) { - tmp = it87_read_value(data, IT87_REG_FAN_16BIT); - if (~tmp & 0x07 & data->has_fan) { - dev_dbg(&pdev->dev, - "Setting fan1-3 to 16-bit mode\n"); - it87_write_value(data, IT87_REG_FAN_16BIT, - tmp | 0x07); - } - /* IT8705F only supports three fans. */ - if (data->type != it87) { - if (tmp & (1 << 4)) - data->has_fan |= (1 << 3); /* fan4 enabled */ - if (tmp & (1 << 5)) - data->has_fan |= (1 << 4); /* fan5 enabled */ - } - } - - /* Fan input pins may be used for alternative functions */ - data->has_fan &= ~sio_data->skip_fan; - - /* Start monitoring */ - it87_write_value(data, IT87_REG_CONFIG, - (it87_read_value(data, IT87_REG_CONFIG) & 0x36) - | (update_vbat ? 0x41 : 0x01)); -} - -static void it87_update_pwm_ctrl(struct it87_data *data, int nr) -{ - data->pwm_ctrl[nr] = it87_read_value(data, IT87_REG_PWM(nr)); - if (has_newer_autopwm(data)) { - data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; - data->pwm_duty[nr] = it87_read_value(data, - IT87_REG_PWM_DUTY(nr)); - } else { - if (data->pwm_ctrl[nr] & 0x80) /* Automatic mode */ - data->pwm_temp_map[nr] = data->pwm_ctrl[nr] & 0x03; - else /* Manual mode */ - data->pwm_duty[nr] = data->pwm_ctrl[nr] & 0x7f; - } - - if (has_old_autopwm(data)) { - int i; - - for (i = 0; i < 5 ; i++) - data->auto_temp[nr][i] = it87_read_value(data, - IT87_REG_AUTO_TEMP(nr, i)); - for (i = 0; i < 3 ; i++) - data->auto_pwm[nr][i] = it87_read_value(data, - IT87_REG_AUTO_PWM(nr, i)); - } -} - -static struct it87_data *it87_update_device(struct device *dev) -{ - struct it87_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - if (update_vbat) { - /* - * Cleared after each update, so reenable. Value - * returned by this read will be previous value - */ - it87_write_value(data, IT87_REG_CONFIG, - it87_read_value(data, IT87_REG_CONFIG) | 0x40); - } - for (i = 0; i <= 7; i++) { - data->in[i] = - it87_read_value(data, IT87_REG_VIN(i)); - data->in_min[i] = - it87_read_value(data, IT87_REG_VIN_MIN(i)); - data->in_max[i] = - it87_read_value(data, IT87_REG_VIN_MAX(i)); - } - /* in8 (battery) has no limit registers */ - data->in[8] = it87_read_value(data, IT87_REG_VIN(8)); - - for (i = 0; i < 5; i++) { - /* Skip disabled fans */ - if (!(data->has_fan & (1 << i))) - continue; - - data->fan_min[i] = - it87_read_value(data, IT87_REG_FAN_MIN[i]); - data->fan[i] = it87_read_value(data, - IT87_REG_FAN[i]); - /* Add high byte if in 16-bit mode */ - if (has_16bit_fans(data)) { - data->fan[i] |= it87_read_value(data, - IT87_REG_FANX[i]) << 8; - data->fan_min[i] |= it87_read_value(data, - IT87_REG_FANX_MIN[i]) << 8; - } - } - for (i = 0; i < 3; i++) { - data->temp[i] = - it87_read_value(data, IT87_REG_TEMP(i)); - data->temp_high[i] = - it87_read_value(data, IT87_REG_TEMP_HIGH(i)); - data->temp_low[i] = - it87_read_value(data, IT87_REG_TEMP_LOW(i)); - } - - /* Newer chips don't have clock dividers */ - if ((data->has_fan & 0x07) && !has_16bit_fans(data)) { - i = it87_read_value(data, IT87_REG_FAN_DIV); - data->fan_div[0] = i & 0x07; - data->fan_div[1] = (i >> 3) & 0x07; - data->fan_div[2] = (i & 0x40) ? 3 : 1; - } - - data->alarms = - it87_read_value(data, IT87_REG_ALARM1) | - (it87_read_value(data, IT87_REG_ALARM2) << 8) | - (it87_read_value(data, IT87_REG_ALARM3) << 16); - data->beeps = it87_read_value(data, IT87_REG_BEEP_ENABLE); - - data->fan_main_ctrl = it87_read_value(data, - IT87_REG_FAN_MAIN_CTRL); - data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL); - for (i = 0; i < 3; i++) - it87_update_pwm_ctrl(data, i); - - data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE); - /* - * The IT8705F does not have VID capability. - * The IT8718F and later don't use IT87_REG_VID for the - * same purpose. - */ - if (data->type == it8712 || data->type == it8716) { - data->vid = it87_read_value(data, IT87_REG_VID); - /* - * The older IT8712F revisions had only 5 VID pins, - * but we assume it is always safe to read 6 bits. - */ - data->vid &= 0x3f; - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static int __init it87_device_add(unsigned short address, - const struct it87_sio_data *sio_data) -{ - struct resource res = { - .start = address + IT87_EC_OFFSET, - .end = address + IT87_EC_OFFSET + IT87_EC_EXTENT - 1, - .name = DRVNAME, - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add_data(pdev, sio_data, - sizeof(struct it87_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init sm_it87_init(void) -{ - int err; - unsigned short isa_address = 0; - struct it87_sio_data sio_data; - - memset(&sio_data, 0, sizeof(struct it87_sio_data)); - err = it87_find(&isa_address, &sio_data); - if (err) - return err; - err = platform_driver_register(&it87_driver); - if (err) - return err; - - err = it87_device_add(isa_address, &sio_data); - if (err) { - platform_driver_unregister(&it87_driver); - return err; - } - - return 0; -} - -static void __exit sm_it87_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&it87_driver); -} - - -MODULE_AUTHOR("Chris Gauthron, " - "Jean Delvare "); -MODULE_DESCRIPTION("IT8705F/IT871xF/IT872xF hardware monitoring driver"); -module_param(update_vbat, bool, 0); -MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value"); -module_param(fix_pwm_polarity, bool, 0); -MODULE_PARM_DESC(fix_pwm_polarity, - "Force PWM polarity to active high (DANGEROUS)"); -MODULE_LICENSE("GPL"); - -module_init(sm_it87_init); -module_exit(sm_it87_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/jc42.c b/ANDROID_3.4.5/drivers/hwmon/jc42.c deleted file mode 100644 index a9bfd673..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/jc42.c +++ /dev/null @@ -1,595 +0,0 @@ -/* - * jc42.c - driver for Jedec JC42.4 compliant temperature sensors - * - * Copyright (c) 2010 Ericsson AB. - * - * Derived from lm77.c by Andras BALI . - * - * JC42.4 compliant temperature sensors are typically used on memory modules. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, I2C_CLIENT_END }; - -/* JC42 registers. All registers are 16 bit. */ -#define JC42_REG_CAP 0x00 -#define JC42_REG_CONFIG 0x01 -#define JC42_REG_TEMP_UPPER 0x02 -#define JC42_REG_TEMP_LOWER 0x03 -#define JC42_REG_TEMP_CRITICAL 0x04 -#define JC42_REG_TEMP 0x05 -#define JC42_REG_MANID 0x06 -#define JC42_REG_DEVICEID 0x07 - -/* Status bits in temperature register */ -#define JC42_ALARM_CRIT_BIT 15 -#define JC42_ALARM_MAX_BIT 14 -#define JC42_ALARM_MIN_BIT 13 - -/* Configuration register defines */ -#define JC42_CFG_CRIT_ONLY (1 << 2) -#define JC42_CFG_TCRIT_LOCK (1 << 6) -#define JC42_CFG_EVENT_LOCK (1 << 7) -#define JC42_CFG_SHUTDOWN (1 << 8) -#define JC42_CFG_HYST_SHIFT 9 -#define JC42_CFG_HYST_MASK 0x03 - -/* Capabilities */ -#define JC42_CAP_RANGE (1 << 2) - -/* Manufacturer IDs */ -#define ADT_MANID 0x11d4 /* Analog Devices */ -#define ATMEL_MANID 0x001f /* Atmel */ -#define MAX_MANID 0x004d /* Maxim */ -#define IDT_MANID 0x00b3 /* IDT */ -#define MCP_MANID 0x0054 /* Microchip */ -#define NXP_MANID 0x1131 /* NXP Semiconductors */ -#define ONS_MANID 0x1b09 /* ON Semiconductor */ -#define STM_MANID 0x104a /* ST Microelectronics */ - -/* Supported chips */ - -/* Analog Devices */ -#define ADT7408_DEVID 0x0801 -#define ADT7408_DEVID_MASK 0xffff - -/* Atmel */ -#define AT30TS00_DEVID 0x8201 -#define AT30TS00_DEVID_MASK 0xffff - -/* IDT */ -#define TS3000B3_DEVID 0x2903 /* Also matches TSE2002B3 */ -#define TS3000B3_DEVID_MASK 0xffff - -#define TS3000GB2_DEVID 0x2912 /* Also matches TSE2002GB2 */ -#define TS3000GB2_DEVID_MASK 0xffff - -/* Maxim */ -#define MAX6604_DEVID 0x3e00 -#define MAX6604_DEVID_MASK 0xffff - -/* Microchip */ -#define MCP9804_DEVID 0x0200 -#define MCP9804_DEVID_MASK 0xfffc - -#define MCP98242_DEVID 0x2000 -#define MCP98242_DEVID_MASK 0xfffc - -#define MCP98243_DEVID 0x2100 -#define MCP98243_DEVID_MASK 0xfffc - -#define MCP9843_DEVID 0x0000 /* Also matches mcp9805 */ -#define MCP9843_DEVID_MASK 0xfffe - -/* NXP */ -#define SE97_DEVID 0xa200 -#define SE97_DEVID_MASK 0xfffc - -#define SE98_DEVID 0xa100 -#define SE98_DEVID_MASK 0xfffc - -/* ON Semiconductor */ -#define CAT6095_DEVID 0x0800 /* Also matches CAT34TS02 */ -#define CAT6095_DEVID_MASK 0xffe0 - -/* ST Microelectronics */ -#define STTS424_DEVID 0x0101 -#define STTS424_DEVID_MASK 0xffff - -#define STTS424E_DEVID 0x0000 -#define STTS424E_DEVID_MASK 0xfffe - -#define STTS2002_DEVID 0x0300 -#define STTS2002_DEVID_MASK 0xffff - -#define STTS3000_DEVID 0x0200 -#define STTS3000_DEVID_MASK 0xffff - -static u16 jc42_hysteresis[] = { 0, 1500, 3000, 6000 }; - -struct jc42_chips { - u16 manid; - u16 devid; - u16 devid_mask; -}; - -static struct jc42_chips jc42_chips[] = { - { ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK }, - { ATMEL_MANID, AT30TS00_DEVID, AT30TS00_DEVID_MASK }, - { IDT_MANID, TS3000B3_DEVID, TS3000B3_DEVID_MASK }, - { IDT_MANID, TS3000GB2_DEVID, TS3000GB2_DEVID_MASK }, - { MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK }, - { MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK }, - { MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK }, - { MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK }, - { MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK }, - { NXP_MANID, SE97_DEVID, SE97_DEVID_MASK }, - { ONS_MANID, CAT6095_DEVID, CAT6095_DEVID_MASK }, - { NXP_MANID, SE98_DEVID, SE98_DEVID_MASK }, - { STM_MANID, STTS424_DEVID, STTS424_DEVID_MASK }, - { STM_MANID, STTS424E_DEVID, STTS424E_DEVID_MASK }, - { STM_MANID, STTS2002_DEVID, STTS2002_DEVID_MASK }, - { STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK }, -}; - -/* Each client has this additional data */ -struct jc42_data { - struct device *hwmon_dev; - struct mutex update_lock; /* protect register access */ - bool extended; /* true if extended range supported */ - bool valid; - unsigned long last_updated; /* In jiffies */ - u16 orig_config; /* original configuration */ - u16 config; /* current configuration */ - u16 temp_input; /* Temperatures */ - u16 temp_crit; - u16 temp_min; - u16 temp_max; -}; - -static int jc42_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info); -static int jc42_remove(struct i2c_client *client); - -static struct jc42_data *jc42_update_device(struct device *dev); - -static const struct i2c_device_id jc42_id[] = { - { "jc42", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, jc42_id); - -#ifdef CONFIG_PM - -static int jc42_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct jc42_data *data = i2c_get_clientdata(client); - - data->config |= JC42_CFG_SHUTDOWN; - i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config); - return 0; -} - -static int jc42_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct jc42_data *data = i2c_get_clientdata(client); - - data->config &= ~JC42_CFG_SHUTDOWN; - i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, data->config); - return 0; -} - -static const struct dev_pm_ops jc42_dev_pm_ops = { - .suspend = jc42_suspend, - .resume = jc42_resume, -}; - -#define JC42_DEV_PM_OPS (&jc42_dev_pm_ops) -#else -#define JC42_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - -/* This is the driver that will be inserted */ -static struct i2c_driver jc42_driver = { - .class = I2C_CLASS_SPD, - .driver = { - .name = "jc42", - .pm = JC42_DEV_PM_OPS, - }, - .probe = jc42_probe, - .remove = jc42_remove, - .id_table = jc42_id, - .detect = jc42_detect, - .address_list = normal_i2c, -}; - -#define JC42_TEMP_MIN_EXTENDED (-40000) -#define JC42_TEMP_MIN 0 -#define JC42_TEMP_MAX 125000 - -static u16 jc42_temp_to_reg(int temp, bool extended) -{ - int ntemp = SENSORS_LIMIT(temp, - extended ? JC42_TEMP_MIN_EXTENDED : - JC42_TEMP_MIN, JC42_TEMP_MAX); - - /* convert from 0.001 to 0.0625 resolution */ - return (ntemp * 2 / 125) & 0x1fff; -} - -static int jc42_temp_from_reg(s16 reg) -{ - reg &= 0x1fff; - - /* sign extend register */ - if (reg & 0x1000) - reg |= 0xf000; - - /* convert from 0.0625 to 0.001 resolution */ - return reg * 125 / 2; -} - -/* sysfs stuff */ - -/* read routines for temperature limits */ -#define show(value) \ -static ssize_t show_##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct jc42_data *data = jc42_update_device(dev); \ - if (IS_ERR(data)) \ - return PTR_ERR(data); \ - return sprintf(buf, "%d\n", jc42_temp_from_reg(data->value)); \ -} - -show(temp_input); -show(temp_crit); -show(temp_min); -show(temp_max); - -/* read routines for hysteresis values */ -static ssize_t show_temp_crit_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct jc42_data *data = jc42_update_device(dev); - int temp, hyst; - - if (IS_ERR(data)) - return PTR_ERR(data); - - temp = jc42_temp_from_reg(data->temp_crit); - hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) - & JC42_CFG_HYST_MASK]; - return sprintf(buf, "%d\n", temp - hyst); -} - -static ssize_t show_temp_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct jc42_data *data = jc42_update_device(dev); - int temp, hyst; - - if (IS_ERR(data)) - return PTR_ERR(data); - - temp = jc42_temp_from_reg(data->temp_max); - hyst = jc42_hysteresis[(data->config >> JC42_CFG_HYST_SHIFT) - & JC42_CFG_HYST_MASK]; - return sprintf(buf, "%d\n", temp - hyst); -} - -/* write routines */ -#define set(value, reg) \ -static ssize_t set_##value(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct jc42_data *data = i2c_get_clientdata(client); \ - int err, ret = count; \ - long val; \ - if (kstrtol(buf, 10, &val) < 0) \ - return -EINVAL; \ - mutex_lock(&data->update_lock); \ - data->value = jc42_temp_to_reg(val, data->extended); \ - err = i2c_smbus_write_word_swapped(client, reg, data->value); \ - if (err < 0) \ - ret = err; \ - mutex_unlock(&data->update_lock); \ - return ret; \ -} - -set(temp_min, JC42_REG_TEMP_LOWER); -set(temp_max, JC42_REG_TEMP_UPPER); -set(temp_crit, JC42_REG_TEMP_CRITICAL); - -/* - * JC42.4 compliant chips only support four hysteresis values. - * Pick best choice and go from there. - */ -static ssize_t set_temp_crit_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct jc42_data *data = i2c_get_clientdata(client); - unsigned long val; - int diff, hyst; - int err; - int ret = count; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - diff = jc42_temp_from_reg(data->temp_crit) - val; - hyst = 0; - if (diff > 0) { - if (diff < 2250) - hyst = 1; /* 1.5 degrees C */ - else if (diff < 4500) - hyst = 2; /* 3.0 degrees C */ - else - hyst = 3; /* 6.0 degrees C */ - } - - mutex_lock(&data->update_lock); - data->config = (data->config - & ~(JC42_CFG_HYST_MASK << JC42_CFG_HYST_SHIFT)) - | (hyst << JC42_CFG_HYST_SHIFT); - err = i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, - data->config); - if (err < 0) - ret = err; - mutex_unlock(&data->update_lock); - return ret; -} - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u16 bit = to_sensor_dev_attr(attr)->index; - struct jc42_data *data = jc42_update_device(dev); - u16 val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = data->temp_input; - if (bit != JC42_ALARM_CRIT_BIT && (data->config & JC42_CFG_CRIT_ONLY)) - val = 0; - return sprintf(buf, "%u\n", (val >> bit) & 1); -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, - show_temp_input, NULL); -static DEVICE_ATTR(temp1_crit, S_IRUGO, - show_temp_crit, set_temp_crit); -static DEVICE_ATTR(temp1_min, S_IRUGO, - show_temp_min, set_temp_min); -static DEVICE_ATTR(temp1_max, S_IRUGO, - show_temp_max, set_temp_max); - -static DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, - show_temp_crit_hyst, set_temp_crit_hyst); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, - show_temp_max_hyst, NULL); - -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, - JC42_ALARM_CRIT_BIT); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, - JC42_ALARM_MIN_BIT); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, - JC42_ALARM_MAX_BIT); - -static struct attribute *jc42_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_crit.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_crit_hyst.attr, - &dev_attr_temp1_max_hyst.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - NULL -}; - -static umode_t jc42_attribute_mode(struct kobject *kobj, - struct attribute *attr, int index) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct i2c_client *client = to_i2c_client(dev); - struct jc42_data *data = i2c_get_clientdata(client); - unsigned int config = data->config; - bool readonly; - - if (attr == &dev_attr_temp1_crit.attr) - readonly = config & JC42_CFG_TCRIT_LOCK; - else if (attr == &dev_attr_temp1_min.attr || - attr == &dev_attr_temp1_max.attr) - readonly = config & JC42_CFG_EVENT_LOCK; - else if (attr == &dev_attr_temp1_crit_hyst.attr) - readonly = config & (JC42_CFG_EVENT_LOCK | JC42_CFG_TCRIT_LOCK); - else - readonly = true; - - return S_IRUGO | (readonly ? 0 : S_IWUSR); -} - -static const struct attribute_group jc42_group = { - .attrs = jc42_attributes, - .is_visible = jc42_attribute_mode, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int i, config, cap, manid, devid; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - cap = i2c_smbus_read_word_swapped(client, JC42_REG_CAP); - config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG); - manid = i2c_smbus_read_word_swapped(client, JC42_REG_MANID); - devid = i2c_smbus_read_word_swapped(client, JC42_REG_DEVICEID); - - if (cap < 0 || config < 0 || manid < 0 || devid < 0) - return -ENODEV; - - if ((cap & 0xff00) || (config & 0xf800)) - return -ENODEV; - - for (i = 0; i < ARRAY_SIZE(jc42_chips); i++) { - struct jc42_chips *chip = &jc42_chips[i]; - if (manid == chip->manid && - (devid & chip->devid_mask) == chip->devid) { - strlcpy(info->type, "jc42", I2C_NAME_SIZE); - return 0; - } - } - return -ENODEV; -} - -static int jc42_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct jc42_data *data; - int config, cap, err; - struct device *dev = &client->dev; - - data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - cap = i2c_smbus_read_word_swapped(client, JC42_REG_CAP); - if (cap < 0) - return cap; - - data->extended = !!(cap & JC42_CAP_RANGE); - - config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG); - if (config < 0) - return config; - - data->orig_config = config; - if (config & JC42_CFG_SHUTDOWN) { - config &= ~JC42_CFG_SHUTDOWN; - i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config); - } - data->config = config; - - /* Register sysfs hooks */ - err = sysfs_create_group(&dev->kobj, &jc42_group); - if (err) - return err; - - 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: - sysfs_remove_group(&dev->kobj, &jc42_group); - return err; -} - -static int jc42_remove(struct i2c_client *client) -{ - struct jc42_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &jc42_group); - if (data->config != data->orig_config) - i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, - data->orig_config); - return 0; -} - -static struct jc42_data *jc42_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct jc42_data *data = i2c_get_clientdata(client); - struct jc42_data *ret = data; - int val; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP); - if (val < 0) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_input = val; - - val = i2c_smbus_read_word_swapped(client, - JC42_REG_TEMP_CRITICAL); - if (val < 0) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_crit = val; - - val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_LOWER); - if (val < 0) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_min = val; - - val = i2c_smbus_read_word_swapped(client, JC42_REG_TEMP_UPPER); - if (val < 0) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_max = val; - - data->last_updated = jiffies; - data->valid = true; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -module_i2c_driver(jc42_driver); - -MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("JC42 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/jz4740-hwmon.c b/ANDROID_3.4.5/drivers/hwmon/jz4740-hwmon.c deleted file mode 100644 index 5253d233..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/jz4740-hwmon.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2009-2010, Lars-Peter Clausen - * JZ4740 SoC HWMON driver - * - * 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. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include - -struct jz4740_hwmon { - struct resource *mem; - void __iomem *base; - - int irq; - - const struct mfd_cell *cell; - struct device *hwmon; - - struct completion read_completion; - - struct mutex lock; -}; - -static ssize_t jz4740_hwmon_show_name(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - return sprintf(buf, "jz4740\n"); -} - -static irqreturn_t jz4740_hwmon_irq(int irq, void *data) -{ - struct jz4740_hwmon *hwmon = data; - - complete(&hwmon->read_completion); - return IRQ_HANDLED; -} - -static ssize_t jz4740_hwmon_read_adcin(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct jz4740_hwmon *hwmon = dev_get_drvdata(dev); - struct completion *completion = &hwmon->read_completion; - long t; - unsigned long val; - int ret; - - mutex_lock(&hwmon->lock); - - INIT_COMPLETION(*completion); - - enable_irq(hwmon->irq); - hwmon->cell->enable(to_platform_device(dev)); - - t = wait_for_completion_interruptible_timeout(completion, HZ); - - if (t > 0) { - val = readw(hwmon->base) & 0xfff; - val = (val * 3300) >> 12; - ret = sprintf(buf, "%lu\n", val); - } else { - ret = t ? t : -ETIMEDOUT; - } - - hwmon->cell->disable(to_platform_device(dev)); - disable_irq(hwmon->irq); - - mutex_unlock(&hwmon->lock); - - return ret; -} - -static DEVICE_ATTR(name, S_IRUGO, jz4740_hwmon_show_name, NULL); -static DEVICE_ATTR(in0_input, S_IRUGO, jz4740_hwmon_read_adcin, NULL); - -static struct attribute *jz4740_hwmon_attributes[] = { - &dev_attr_name.attr, - &dev_attr_in0_input.attr, - NULL -}; - -static const struct attribute_group jz4740_hwmon_attr_group = { - .attrs = jz4740_hwmon_attributes, -}; - -static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) -{ - int ret; - struct jz4740_hwmon *hwmon; - - hwmon = kmalloc(sizeof(*hwmon), GFP_KERNEL); - if (!hwmon) { - dev_err(&pdev->dev, "Failed to allocate driver structure\n"); - return -ENOMEM; - } - - hwmon->cell = mfd_get_cell(pdev); - - hwmon->irq = platform_get_irq(pdev, 0); - if (hwmon->irq < 0) { - ret = hwmon->irq; - dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); - goto err_free; - } - - hwmon->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!hwmon->mem) { - ret = -ENOENT; - dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); - goto err_free; - } - - hwmon->mem = request_mem_region(hwmon->mem->start, - resource_size(hwmon->mem), pdev->name); - if (!hwmon->mem) { - ret = -EBUSY; - dev_err(&pdev->dev, "Failed to request mmio memory region\n"); - goto err_free; - } - - hwmon->base = ioremap_nocache(hwmon->mem->start, - resource_size(hwmon->mem)); - if (!hwmon->base) { - ret = -EBUSY; - dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); - goto err_release_mem_region; - } - - init_completion(&hwmon->read_completion); - mutex_init(&hwmon->lock); - - platform_set_drvdata(pdev, hwmon); - - ret = request_irq(hwmon->irq, jz4740_hwmon_irq, 0, pdev->name, hwmon); - if (ret) { - dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); - goto err_iounmap; - } - disable_irq(hwmon->irq); - - ret = sysfs_create_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); - if (ret) { - dev_err(&pdev->dev, "Failed to create sysfs group: %d\n", ret); - goto err_free_irq; - } - - hwmon->hwmon = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon->hwmon)) { - ret = PTR_ERR(hwmon->hwmon); - goto err_remove_file; - } - - return 0; - -err_remove_file: - sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); -err_free_irq: - free_irq(hwmon->irq, hwmon); -err_iounmap: - platform_set_drvdata(pdev, NULL); - iounmap(hwmon->base); -err_release_mem_region: - release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); -err_free: - kfree(hwmon); - - return ret; -} - -static int __devexit jz4740_hwmon_remove(struct platform_device *pdev) -{ - struct jz4740_hwmon *hwmon = platform_get_drvdata(pdev); - - hwmon_device_unregister(hwmon->hwmon); - sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); - - free_irq(hwmon->irq, hwmon); - - iounmap(hwmon->base); - release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); - - platform_set_drvdata(pdev, NULL); - kfree(hwmon); - - return 0; -} - -static struct platform_driver jz4740_hwmon_driver = { - .probe = jz4740_hwmon_probe, - .remove = __devexit_p(jz4740_hwmon_remove), - .driver = { - .name = "jz4740-hwmon", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(jz4740_hwmon_driver); - -MODULE_DESCRIPTION("JZ4740 SoC HWMON driver"); -MODULE_AUTHOR("Lars-Peter Clausen "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:jz4740-hwmon"); diff --git a/ANDROID_3.4.5/drivers/hwmon/k10temp.c b/ANDROID_3.4.5/drivers/hwmon/k10temp.c deleted file mode 100644 index 307bb325..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/k10temp.c +++ /dev/null @@ -1,239 +0,0 @@ -/* - * k10temp.c - AMD Family 10h/11h/12h/14h/15h processor hardware monitoring - * - * Copyright (c) 2009 Clemens Ladisch - * - * - * This driver is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License; either - * version 2 of the License, or (at your option) any later version. - * - * This driver 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 driver; if not, see . - */ - -#include -#include -#include -#include -#include -#include -#include - -MODULE_DESCRIPTION("AMD Family 10h+ CPU core temperature monitor"); -MODULE_AUTHOR("Clemens Ladisch "); -MODULE_LICENSE("GPL"); - -static bool force; -module_param(force, bool, 0444); -MODULE_PARM_DESC(force, "force loading on processors with erratum 319"); - -/* PCI-IDs for Northbridge devices not used anywhere else */ -#define PCI_DEVICE_ID_AMD_15H_M10H_NB_F3 0x1403 - -/* CPUID function 0x80000001, ebx */ -#define CPUID_PKGTYPE_MASK 0xf0000000 -#define CPUID_PKGTYPE_F 0x00000000 -#define CPUID_PKGTYPE_AM2R2_AM3 0x10000000 - -/* DRAM controller (PCI function 2) */ -#define REG_DCT0_CONFIG_HIGH 0x094 -#define DDR3_MODE 0x00000100 - -/* miscellaneous (PCI function 3) */ -#define REG_HARDWARE_THERMAL_CONTROL 0x64 -#define HTC_ENABLE 0x00000001 - -#define REG_REPORTED_TEMPERATURE 0xa4 - -#define REG_NORTHBRIDGE_CAPABILITIES 0xe8 -#define NB_CAP_HTC 0x00000400 - -static ssize_t show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - u32 regval; - - pci_read_config_dword(to_pci_dev(dev), - REG_REPORTED_TEMPERATURE, ®val); - return sprintf(buf, "%u\n", (regval >> 21) * 125); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "%d\n", 70 * 1000); -} - -static ssize_t show_temp_crit(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - int show_hyst = attr->index; - u32 regval; - int value; - - pci_read_config_dword(to_pci_dev(dev), - REG_HARDWARE_THERMAL_CONTROL, ®val); - value = ((regval >> 16) & 0x7f) * 500 + 52000; - if (show_hyst) - value -= ((regval >> 24) & 0xf) * 500; - return sprintf(buf, "%d\n", value); -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "k10temp\n"); -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); -static DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, show_temp_crit, NULL, 1); -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static bool __devinit has_erratum_319(struct pci_dev *pdev) -{ - u32 pkg_type, reg_dram_cfg; - - if (boot_cpu_data.x86 != 0x10) - return false; - - /* - * Erratum 319: The thermal sensor of Socket F/AM2+ processors - * may be unreliable. - */ - pkg_type = cpuid_ebx(0x80000001) & CPUID_PKGTYPE_MASK; - if (pkg_type == CPUID_PKGTYPE_F) - return true; - if (pkg_type != CPUID_PKGTYPE_AM2R2_AM3) - return false; - - /* DDR3 memory implies socket AM3, which is good */ - pci_bus_read_config_dword(pdev->bus, - PCI_DEVFN(PCI_SLOT(pdev->devfn), 2), - REG_DCT0_CONFIG_HIGH, ®_dram_cfg); - if (reg_dram_cfg & DDR3_MODE) - return false; - - /* - * Unfortunately it is possible to run a socket AM3 CPU with DDR2 - * memory. We blacklist all the cores which do exist in socket AM2+ - * format. It still isn't perfect, as RB-C2 cores exist in both AM2+ - * and AM3 formats, but that's the best we can do. - */ - return boot_cpu_data.x86_model < 4 || - (boot_cpu_data.x86_model == 4 && boot_cpu_data.x86_mask <= 2); -} - -static int __devinit k10temp_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct device *hwmon_dev; - u32 reg_caps, reg_htc; - int unreliable = has_erratum_319(pdev); - int err; - - if (unreliable && !force) { - dev_err(&pdev->dev, - "unreliable CPU thermal sensor; monitoring disabled\n"); - err = -ENODEV; - goto exit; - } - - err = device_create_file(&pdev->dev, &dev_attr_temp1_input); - if (err) - goto exit; - err = device_create_file(&pdev->dev, &dev_attr_temp1_max); - if (err) - goto exit_remove; - - pci_read_config_dword(pdev, REG_NORTHBRIDGE_CAPABILITIES, ®_caps); - pci_read_config_dword(pdev, REG_HARDWARE_THERMAL_CONTROL, ®_htc); - if ((reg_caps & NB_CAP_HTC) && (reg_htc & HTC_ENABLE)) { - err = device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_crit.dev_attr); - if (err) - goto exit_remove; - err = device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_crit_hyst.dev_attr); - if (err) - goto exit_remove; - } - - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_remove; - - hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon_dev)) { - err = PTR_ERR(hwmon_dev); - goto exit_remove; - } - pci_set_drvdata(pdev, hwmon_dev); - - if (unreliable && force) - dev_warn(&pdev->dev, - "unreliable CPU thermal sensor; check erratum 319\n"); - return 0; - -exit_remove: - device_remove_file(&pdev->dev, &dev_attr_name); - device_remove_file(&pdev->dev, &dev_attr_temp1_input); - device_remove_file(&pdev->dev, &dev_attr_temp1_max); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp1_crit.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp1_crit_hyst.dev_attr); -exit: - return err; -} - -static void __devexit k10temp_remove(struct pci_dev *pdev) -{ - hwmon_device_unregister(pci_get_drvdata(pdev)); - device_remove_file(&pdev->dev, &dev_attr_name); - device_remove_file(&pdev->dev, &dev_attr_temp1_input); - device_remove_file(&pdev->dev, &dev_attr_temp1_max); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp1_crit.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp1_crit_hyst.dev_attr); - pci_set_drvdata(pdev, NULL); -} - -static DEFINE_PCI_DEVICE_TABLE(k10temp_id_table) = { - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_11H_NB_MISC) }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) }, - { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M10H_NB_F3) }, - {} -}; -MODULE_DEVICE_TABLE(pci, k10temp_id_table); - -static struct pci_driver k10temp_driver = { - .name = "k10temp", - .id_table = k10temp_id_table, - .probe = k10temp_probe, - .remove = __devexit_p(k10temp_remove), -}; - -static int __init k10temp_init(void) -{ - return pci_register_driver(&k10temp_driver); -} - -static void __exit k10temp_exit(void) -{ - pci_unregister_driver(&k10temp_driver); -} - -module_init(k10temp_init) -module_exit(k10temp_exit) diff --git a/ANDROID_3.4.5/drivers/hwmon/k8temp.c b/ANDROID_3.4.5/drivers/hwmon/k8temp.c deleted file mode 100644 index 57510198..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/k8temp.c +++ /dev/null @@ -1,357 +0,0 @@ -/* - * k8temp.c - Linux kernel module for hardware monitoring - * - * Copyright (C) 2006 Rudolf Marek - * - * Inspired from the w83785 and amd756 drivers. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define TEMP_FROM_REG(val) (((((val) >> 16) & 0xff) - 49) * 1000) -#define REG_TEMP 0xe4 -#define SEL_PLACE 0x40 -#define SEL_CORE 0x04 - -struct k8temp_data { - struct device *hwmon_dev; - struct mutex update_lock; - const char *name; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - u8 sensorsp; /* sensor presence bits - SEL_CORE, SEL_PLACE */ - u32 temp[2][2]; /* core, place */ - u8 swap_core_select; /* meaning of SEL_CORE is inverted */ - u32 temp_offset; -}; - -static struct k8temp_data *k8temp_update_device(struct device *dev) -{ - struct k8temp_data *data = dev_get_drvdata(dev); - struct pci_dev *pdev = to_pci_dev(dev); - u8 tmp; - - mutex_lock(&data->update_lock); - - if (!data->valid - || time_after(jiffies, data->last_updated + HZ)) { - pci_read_config_byte(pdev, REG_TEMP, &tmp); - tmp &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */ - pci_write_config_byte(pdev, REG_TEMP, tmp); - pci_read_config_dword(pdev, REG_TEMP, &data->temp[0][0]); - - if (data->sensorsp & SEL_PLACE) { - tmp |= SEL_PLACE; /* Select sensor 1, core0 */ - pci_write_config_byte(pdev, REG_TEMP, tmp); - pci_read_config_dword(pdev, REG_TEMP, - &data->temp[0][1]); - } - - if (data->sensorsp & SEL_CORE) { - tmp &= ~SEL_PLACE; /* Select sensor 0, core1 */ - tmp |= SEL_CORE; - pci_write_config_byte(pdev, REG_TEMP, tmp); - pci_read_config_dword(pdev, REG_TEMP, - &data->temp[1][0]); - - if (data->sensorsp & SEL_PLACE) { - tmp |= SEL_PLACE; /* Select sensor 1, core1 */ - pci_write_config_byte(pdev, REG_TEMP, tmp); - pci_read_config_dword(pdev, REG_TEMP, - &data->temp[1][1]); - } - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - return data; -} - -/* - * Sysfs stuff - */ - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct k8temp_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} - - -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute_2 *attr = - to_sensor_dev_attr_2(devattr); - int core = attr->nr; - int place = attr->index; - int temp; - struct k8temp_data *data = k8temp_update_device(dev); - - if (data->swap_core_select && (data->sensorsp & SEL_CORE)) - core = core ? 0 : 1; - - temp = TEMP_FROM_REG(data->temp[core][place]) + data->temp_offset; - - return sprintf(buf, "%d\n", temp); -} - -/* core, place */ - -static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 1); -static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 1, 0); -static SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 1, 1); -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) }, - { 0 }, -}; - -MODULE_DEVICE_TABLE(pci, k8temp_ids); - -static int __devinit is_rev_g_desktop(u8 model) -{ - u32 brandidx; - - if (model < 0x69) - return 0; - - if (model == 0xc1 || model == 0x6c || model == 0x7c) - return 0; - - /* - * Differentiate between AM2 and ASB1. - * See "Constructing the processor Name String" in "Revision - * Guide for AMD NPT Family 0Fh Processors" (33610). - */ - brandidx = cpuid_ebx(0x80000001); - brandidx = (brandidx >> 9) & 0x1f; - - /* Single core */ - if ((model == 0x6f || model == 0x7f) && - (brandidx == 0x7 || brandidx == 0x9 || brandidx == 0xc)) - return 0; - - /* Dual core */ - if (model == 0x6b && - (brandidx == 0xb || brandidx == 0xc)) - return 0; - - return 1; -} - -static int __devinit k8temp_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - int err; - u8 scfg; - u32 temp; - u8 model, stepping; - struct k8temp_data *data; - - data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - model = boot_cpu_data.x86_model; - stepping = boot_cpu_data.x86_mask; - - /* feature available since SH-C0, exclude older revisions */ - if (((model == 4) && (stepping == 0)) || - ((model == 5) && (stepping <= 1))) { - err = -ENODEV; - goto exit_free; - } - - /* - * AMD NPT family 0fh, i.e. RevF and RevG: - * meaning of SEL_CORE bit is inverted - */ - if (model >= 0x40) { - data->swap_core_select = 1; - dev_warn(&pdev->dev, "Temperature readouts might be wrong - " - "check erratum #141\n"); - } - - /* - * RevG desktop CPUs (i.e. no socket S1G1 or ASB1 parts) need - * additional offset, otherwise reported temperature is below - * ambient temperature - */ - if (is_rev_g_desktop(model)) - data->temp_offset = 21000; - - pci_read_config_byte(pdev, REG_TEMP, &scfg); - scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */ - pci_write_config_byte(pdev, REG_TEMP, scfg); - pci_read_config_byte(pdev, REG_TEMP, &scfg); - - if (scfg & (SEL_PLACE | SEL_CORE)) { - dev_err(&pdev->dev, "Configuration bit(s) stuck at 1!\n"); - err = -ENODEV; - goto exit_free; - } - - scfg |= (SEL_PLACE | SEL_CORE); - pci_write_config_byte(pdev, REG_TEMP, scfg); - - /* now we know if we can change core and/or sensor */ - pci_read_config_byte(pdev, REG_TEMP, &data->sensorsp); - - if (data->sensorsp & SEL_PLACE) { - scfg &= ~SEL_CORE; /* Select sensor 1, core0 */ - pci_write_config_byte(pdev, REG_TEMP, scfg); - pci_read_config_dword(pdev, REG_TEMP, &temp); - scfg |= SEL_CORE; /* prepare for next selection */ - if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is unlikely */ - data->sensorsp &= ~SEL_PLACE; - } - - if (data->sensorsp & SEL_CORE) { - scfg &= ~SEL_PLACE; /* Select sensor 0, core1 */ - pci_write_config_byte(pdev, REG_TEMP, scfg); - pci_read_config_dword(pdev, REG_TEMP, &temp); - if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is unlikely */ - data->sensorsp &= ~SEL_CORE; - } - - data->name = "k8temp"; - mutex_init(&data->update_lock); - pci_set_drvdata(pdev, data); - - /* Register sysfs hooks */ - err = device_create_file(&pdev->dev, - &sensor_dev_attr_temp1_input.dev_attr); - if (err) - goto exit_remove; - - /* sensor can be changed and reports something */ - if (data->sensorsp & SEL_PLACE) { - err = device_create_file(&pdev->dev, - &sensor_dev_attr_temp2_input.dev_attr); - if (err) - goto exit_remove; - } - - /* core can be changed and reports something */ - if (data->sensorsp & SEL_CORE) { - err = device_create_file(&pdev->dev, - &sensor_dev_attr_temp3_input.dev_attr); - if (err) - goto exit_remove; - if (data->sensorsp & SEL_PLACE) { - err = device_create_file(&pdev->dev, - &sensor_dev_attr_temp4_input. - dev_attr); - if (err) - goto exit_remove; - } - } - - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_remove; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp2_input.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp3_input.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp4_input.dev_attr); - device_remove_file(&pdev->dev, &dev_attr_name); -exit_free: - pci_set_drvdata(pdev, NULL); - kfree(data); -exit: - return err; -} - -static void __devexit k8temp_remove(struct pci_dev *pdev) -{ - struct k8temp_data *data = pci_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp2_input.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp3_input.dev_attr); - device_remove_file(&pdev->dev, - &sensor_dev_attr_temp4_input.dev_attr); - device_remove_file(&pdev->dev, &dev_attr_name); - pci_set_drvdata(pdev, NULL); - kfree(data); -} - -static struct pci_driver k8temp_driver = { - .name = "k8temp", - .id_table = k8temp_ids, - .probe = k8temp_probe, - .remove = __devexit_p(k8temp_remove), -}; - -static int __init k8temp_init(void) -{ - return pci_register_driver(&k8temp_driver); -} - -static void __exit k8temp_exit(void) -{ - pci_unregister_driver(&k8temp_driver); -} - -MODULE_AUTHOR("Rudolf Marek "); -MODULE_DESCRIPTION("AMD K8 core temperature monitor"); -MODULE_LICENSE("GPL"); - -module_init(k8temp_init) -module_exit(k8temp_exit) diff --git a/ANDROID_3.4.5/drivers/hwmon/lineage-pem.c b/ANDROID_3.4.5/drivers/hwmon/lineage-pem.c deleted file mode 100644 index d264937c..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lineage-pem.c +++ /dev/null @@ -1,572 +0,0 @@ -/* - * Driver for Lineage Compact Power Line series of power entry modules. - * - * Copyright (C) 2010, 2011 Ericsson AB. - * - * Documentation: - * http://www.lineagepower.com/oem/pdf/CPLI2C.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * This driver supports various Lineage Compact Power Line DC/DC and AC/DC - * converters such as CP1800, CP2000AC, CP2000DC, CP2100DC, and others. - * - * The devices are nominally PMBus compliant. However, most standard PMBus - * commands are not supported. Specifically, all hardware monitoring and - * status reporting commands are non-standard. For this reason, a standard - * PMBus driver can not be used. - * - * All Lineage CPL devices have a built-in I2C bus master selector (PCA9541). - * To ensure device access, this driver should only be used as client driver - * to the pca9541 I2C master selector driver. - */ - -/* Command codes */ -#define PEM_OPERATION 0x01 -#define PEM_CLEAR_INFO_FLAGS 0x03 -#define PEM_VOUT_COMMAND 0x21 -#define PEM_VOUT_OV_FAULT_LIMIT 0x40 -#define PEM_READ_DATA_STRING 0xd0 -#define PEM_READ_INPUT_STRING 0xdc -#define PEM_READ_FIRMWARE_REV 0xdd -#define PEM_READ_RUN_TIMER 0xde -#define PEM_FAN_HI_SPEED 0xdf -#define PEM_FAN_NORMAL_SPEED 0xe0 -#define PEM_READ_FAN_SPEED 0xe1 - -/* offsets in data string */ -#define PEM_DATA_STATUS_2 0 -#define PEM_DATA_STATUS_1 1 -#define PEM_DATA_ALARM_2 2 -#define PEM_DATA_ALARM_1 3 -#define PEM_DATA_VOUT_LSB 4 -#define PEM_DATA_VOUT_MSB 5 -#define PEM_DATA_CURRENT 6 -#define PEM_DATA_TEMP 7 - -/* Virtual entries, to report constants */ -#define PEM_DATA_TEMP_MAX 10 -#define PEM_DATA_TEMP_CRIT 11 - -/* offsets in input string */ -#define PEM_INPUT_VOLTAGE 0 -#define PEM_INPUT_POWER_LSB 1 -#define PEM_INPUT_POWER_MSB 2 - -/* offsets in fan data */ -#define PEM_FAN_ADJUSTMENT 0 -#define PEM_FAN_FAN1 1 -#define PEM_FAN_FAN2 2 -#define PEM_FAN_FAN3 3 - -/* Status register bits */ -#define STS1_OUTPUT_ON (1 << 0) -#define STS1_LEDS_FLASHING (1 << 1) -#define STS1_EXT_FAULT (1 << 2) -#define STS1_SERVICE_LED_ON (1 << 3) -#define STS1_SHUTDOWN_OCCURRED (1 << 4) -#define STS1_INT_FAULT (1 << 5) -#define STS1_ISOLATION_TEST_OK (1 << 6) - -#define STS2_ENABLE_PIN_HI (1 << 0) -#define STS2_DATA_OUT_RANGE (1 << 1) -#define STS2_RESTARTED_OK (1 << 1) -#define STS2_ISOLATION_TEST_FAIL (1 << 3) -#define STS2_HIGH_POWER_CAP (1 << 4) -#define STS2_INVALID_INSTR (1 << 5) -#define STS2_WILL_RESTART (1 << 6) -#define STS2_PEC_ERR (1 << 7) - -/* Alarm register bits */ -#define ALRM1_VIN_OUT_LIMIT (1 << 0) -#define ALRM1_VOUT_OUT_LIMIT (1 << 1) -#define ALRM1_OV_VOLT_SHUTDOWN (1 << 2) -#define ALRM1_VIN_OVERCURRENT (1 << 3) -#define ALRM1_TEMP_WARNING (1 << 4) -#define ALRM1_TEMP_SHUTDOWN (1 << 5) -#define ALRM1_PRIMARY_FAULT (1 << 6) -#define ALRM1_POWER_LIMIT (1 << 7) - -#define ALRM2_5V_OUT_LIMIT (1 << 1) -#define ALRM2_TEMP_FAULT (1 << 2) -#define ALRM2_OV_LOW (1 << 3) -#define ALRM2_DCDC_TEMP_HIGH (1 << 4) -#define ALRM2_PRI_TEMP_HIGH (1 << 5) -#define ALRM2_NO_PRIMARY (1 << 6) -#define ALRM2_FAN_FAULT (1 << 7) - -#define FIRMWARE_REV_LEN 4 -#define DATA_STRING_LEN 9 -#define INPUT_STRING_LEN 5 /* 4 for most devices */ -#define FAN_SPEED_LEN 5 - -struct pem_data { - struct device *hwmon_dev; - - struct mutex update_lock; - bool valid; - bool fans_supported; - int input_length; - unsigned long last_updated; /* in jiffies */ - - u8 firmware_rev[FIRMWARE_REV_LEN]; - u8 data_string[DATA_STRING_LEN]; - u8 input_string[INPUT_STRING_LEN]; - u8 fan_speed[FAN_SPEED_LEN]; -}; - -static int pem_read_block(struct i2c_client *client, u8 command, u8 *data, - int data_len) -{ - u8 block_buffer[I2C_SMBUS_BLOCK_MAX]; - int result; - - result = i2c_smbus_read_block_data(client, command, block_buffer); - if (unlikely(result < 0)) - goto abort; - if (unlikely(result == 0xff || result != data_len)) { - result = -EIO; - goto abort; - } - memcpy(data, block_buffer, data_len); - result = 0; -abort: - return result; -} - -static struct pem_data *pem_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pem_data *data = i2c_get_clientdata(client); - struct pem_data *ret = data; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int result; - - /* Read data string */ - result = pem_read_block(client, PEM_READ_DATA_STRING, - data->data_string, - sizeof(data->data_string)); - if (unlikely(result < 0)) { - ret = ERR_PTR(result); - goto abort; - } - - /* Read input string */ - if (data->input_length) { - result = pem_read_block(client, PEM_READ_INPUT_STRING, - data->input_string, - data->input_length); - if (unlikely(result < 0)) { - ret = ERR_PTR(result); - goto abort; - } - } - - /* Read fan speeds */ - if (data->fans_supported) { - result = pem_read_block(client, PEM_READ_FAN_SPEED, - data->fan_speed, - sizeof(data->fan_speed)); - if (unlikely(result < 0)) { - ret = ERR_PTR(result); - goto abort; - } - } - - i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS); - - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -static long pem_get_data(u8 *data, int len, int index) -{ - long val; - - switch (index) { - case PEM_DATA_VOUT_LSB: - val = (data[index] + (data[index+1] << 8)) * 5 / 2; - break; - case PEM_DATA_CURRENT: - val = data[index] * 200; - break; - case PEM_DATA_TEMP: - val = data[index] * 1000; - break; - case PEM_DATA_TEMP_MAX: - val = 97 * 1000; /* 97 degrees C per datasheet */ - break; - case PEM_DATA_TEMP_CRIT: - val = 107 * 1000; /* 107 degrees C per datasheet */ - break; - default: - WARN_ON_ONCE(1); - val = 0; - } - return val; -} - -static long pem_get_input(u8 *data, int len, int index) -{ - long val; - - switch (index) { - case PEM_INPUT_VOLTAGE: - if (len == INPUT_STRING_LEN) - val = (data[index] + (data[index+1] << 8) - 75) * 1000; - else - val = (data[index] - 75) * 1000; - break; - case PEM_INPUT_POWER_LSB: - if (len == INPUT_STRING_LEN) - index++; - val = (data[index] + (data[index+1] << 8)) * 1000000L; - break; - default: - WARN_ON_ONCE(1); - val = 0; - } - return val; -} - -static long pem_get_fan(u8 *data, int len, int index) -{ - long val; - - switch (index) { - case PEM_FAN_FAN1: - case PEM_FAN_FAN2: - case PEM_FAN_FAN3: - val = data[index] * 100; - break; - default: - WARN_ON_ONCE(1); - val = 0; - } - return val; -} - -/* - * Show boolean, either a fault or an alarm. - * .nr points to the register, .index is the bit mask to check - */ -static ssize_t pem_show_bool(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); - struct pem_data *data = pem_update_device(dev); - u8 status; - - if (IS_ERR(data)) - return PTR_ERR(data); - - status = data->data_string[attr->nr] & attr->index; - return snprintf(buf, PAGE_SIZE, "%d\n", !!status); -} - -static ssize_t pem_show_data(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct pem_data *data = pem_update_device(dev); - long value; - - if (IS_ERR(data)) - return PTR_ERR(data); - - value = pem_get_data(data->data_string, sizeof(data->data_string), - attr->index); - - return snprintf(buf, PAGE_SIZE, "%ld\n", value); -} - -static ssize_t pem_show_input(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct pem_data *data = pem_update_device(dev); - long value; - - if (IS_ERR(data)) - return PTR_ERR(data); - - value = pem_get_input(data->input_string, sizeof(data->input_string), - attr->index); - - return snprintf(buf, PAGE_SIZE, "%ld\n", value); -} - -static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct pem_data *data = pem_update_device(dev); - long value; - - if (IS_ERR(data)) - return PTR_ERR(data); - - value = pem_get_fan(data->fan_speed, sizeof(data->fan_speed), - attr->index); - - return snprintf(buf, PAGE_SIZE, "%ld\n", value); -} - -/* Voltages */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, pem_show_data, NULL, - PEM_DATA_VOUT_LSB); -static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_VOUT_OUT_LIMIT); -static SENSOR_DEVICE_ATTR_2(in1_crit_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_OV_VOLT_SHUTDOWN); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, pem_show_input, NULL, - PEM_INPUT_VOLTAGE); -static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, - ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT); - -/* Currents */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, pem_show_data, NULL, - PEM_DATA_CURRENT); -static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_VIN_OVERCURRENT); - -/* Power */ -static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pem_show_input, NULL, - PEM_INPUT_POWER_LSB); -static SENSOR_DEVICE_ATTR_2(power1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_POWER_LIMIT); - -/* Fans */ -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pem_show_fan, NULL, - PEM_FAN_FAN1); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, pem_show_fan, NULL, - PEM_FAN_FAN2); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, pem_show_fan, NULL, - PEM_FAN_FAN3); -static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_2, ALRM2_FAN_FAULT); - -/* Temperatures */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pem_show_data, NULL, - PEM_DATA_TEMP); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, pem_show_data, NULL, - PEM_DATA_TEMP_MAX); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, pem_show_data, NULL, - PEM_DATA_TEMP_CRIT); -static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_TEMP_WARNING); -static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_1, ALRM1_TEMP_SHUTDOWN); -static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, pem_show_bool, NULL, - PEM_DATA_ALARM_2, ALRM2_TEMP_FAULT); - -static struct attribute *pem_attributes[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - - &sensor_dev_attr_curr1_alarm.dev_attr.attr, - - &sensor_dev_attr_power1_alarm.dev_attr.attr, - - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - - NULL, -}; - -static const struct attribute_group pem_group = { - .attrs = pem_attributes, -}; - -static struct attribute *pem_input_attributes[] = { - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_curr1_input.dev_attr.attr, - &sensor_dev_attr_power1_input.dev_attr.attr, -}; - -static const struct attribute_group pem_input_group = { - .attrs = pem_input_attributes, -}; - -static struct attribute *pem_fan_attributes[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, -}; - -static const struct attribute_group pem_fan_group = { - .attrs = pem_fan_attributes, -}; - -static int pem_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct pem_data *data; - int ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA - | I2C_FUNC_SMBUS_WRITE_BYTE)) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* - * We use the next two commands to determine if the device is really - * there. - */ - ret = pem_read_block(client, PEM_READ_FIRMWARE_REV, - data->firmware_rev, sizeof(data->firmware_rev)); - if (ret < 0) - return ret; - - ret = i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS); - if (ret < 0) - return ret; - - dev_info(&client->dev, "Firmware revision %d.%d.%d\n", - data->firmware_rev[0], data->firmware_rev[1], - data->firmware_rev[2]); - - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, &pem_group); - if (ret) - return ret; - - /* - * Check if input readings are supported. - * This is the case if we can read input data, - * and if the returned data is not all zeros. - * Note that input alarms are always supported. - */ - ret = pem_read_block(client, PEM_READ_INPUT_STRING, - data->input_string, - sizeof(data->input_string) - 1); - if (!ret && (data->input_string[0] || data->input_string[1] || - data->input_string[2])) - data->input_length = sizeof(data->input_string) - 1; - else if (ret < 0) { - /* Input string is one byte longer for some devices */ - ret = pem_read_block(client, PEM_READ_INPUT_STRING, - data->input_string, - sizeof(data->input_string)); - if (!ret && (data->input_string[0] || data->input_string[1] || - data->input_string[2] || data->input_string[3])) - data->input_length = sizeof(data->input_string); - } - ret = 0; - if (data->input_length) { - ret = sysfs_create_group(&client->dev.kobj, &pem_input_group); - if (ret) - goto out_remove_groups; - } - - /* - * Check if fan speed readings are supported. - * This is the case if we can read fan speed data, - * and if the returned data is not all zeros. - * Note that the fan alarm is always supported. - */ - ret = pem_read_block(client, PEM_READ_FAN_SPEED, - data->fan_speed, - sizeof(data->fan_speed)); - if (!ret && (data->fan_speed[0] || data->fan_speed[1] || - data->fan_speed[2] || data->fan_speed[3])) { - data->fans_supported = true; - ret = sysfs_create_group(&client->dev.kobj, &pem_fan_group); - if (ret) - goto out_remove_groups; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_remove_groups; - } - - return 0; - -out_remove_groups: - sysfs_remove_group(&client->dev.kobj, &pem_input_group); - sysfs_remove_group(&client->dev.kobj, &pem_fan_group); - sysfs_remove_group(&client->dev.kobj, &pem_group); - return ret; -} - -static int pem_remove(struct i2c_client *client) -{ - struct pem_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - - sysfs_remove_group(&client->dev.kobj, &pem_input_group); - sysfs_remove_group(&client->dev.kobj, &pem_fan_group); - sysfs_remove_group(&client->dev.kobj, &pem_group); - - return 0; -} - -static const struct i2c_device_id pem_id[] = { - {"lineage_pem", 0}, - {} -}; -MODULE_DEVICE_TABLE(i2c, pem_id); - -static struct i2c_driver pem_driver = { - .driver = { - .name = "lineage_pem", - }, - .probe = pem_probe, - .remove = pem_remove, - .id_table = pem_id, -}; - -module_i2c_driver(pem_driver); - -MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("Lineage CPL PEM hardware monitoring driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm63.c b/ANDROID_3.4.5/drivers/hwmon/lm63.c deleted file mode 100644 index 602a0f0b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm63.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* - * lm63.c - driver for the National Semiconductor LM63 temperature sensor - * with integrated fan control - * Copyright (C) 2004-2008 Jean Delvare - * Based on the lm90 driver. - * - * The LM63 is a sensor chip made by National Semiconductor. It measures - * two temperatures (its own and one external one) and the speed of one - * fan, those speed it can additionally control. Complete datasheet can be - * obtained from National's website at: - * http://www.national.com/pf/LM/LM63.html - * - * The LM63 is basically an LM86 with fan speed monitoring and control - * capabilities added. It misses some of the LM86 features though: - * - No low limit for local temperature. - * - No critical limit for local temperature. - * - Critical limit for remote temperature can be changed only once. We - * will consider that the critical limit is read-only. - * - * The datasheet isn't very clear about what the tachometer reading is. - * I had a explanation from National Semiconductor though. The two lower - * bits of the read value have to be masked out. The value is still 16 bit - * in width. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - * Address is fully defined internally and cannot be changed except for - * LM64 which has one pin dedicated to address selection. - * LM63 and LM96163 have address 0x4c. - * LM64 can have address 0x18 or 0x4e. - */ - -static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; - -/* - * The LM63 registers - */ - -#define LM63_REG_CONFIG1 0x03 -#define LM63_REG_CONVRATE 0x04 -#define LM63_REG_CONFIG2 0xBF -#define LM63_REG_CONFIG_FAN 0x4A - -#define LM63_REG_TACH_COUNT_MSB 0x47 -#define LM63_REG_TACH_COUNT_LSB 0x46 -#define LM63_REG_TACH_LIMIT_MSB 0x49 -#define LM63_REG_TACH_LIMIT_LSB 0x48 - -#define LM63_REG_PWM_VALUE 0x4C -#define LM63_REG_PWM_FREQ 0x4D -#define LM63_REG_LUT_TEMP_HYST 0x4F -#define LM63_REG_LUT_TEMP(nr) (0x50 + 2 * (nr)) -#define LM63_REG_LUT_PWM(nr) (0x51 + 2 * (nr)) - -#define LM63_REG_LOCAL_TEMP 0x00 -#define LM63_REG_LOCAL_HIGH 0x05 - -#define LM63_REG_REMOTE_TEMP_MSB 0x01 -#define LM63_REG_REMOTE_TEMP_LSB 0x10 -#define LM63_REG_REMOTE_OFFSET_MSB 0x11 -#define LM63_REG_REMOTE_OFFSET_LSB 0x12 -#define LM63_REG_REMOTE_HIGH_MSB 0x07 -#define LM63_REG_REMOTE_HIGH_LSB 0x13 -#define LM63_REG_REMOTE_LOW_MSB 0x08 -#define LM63_REG_REMOTE_LOW_LSB 0x14 -#define LM63_REG_REMOTE_TCRIT 0x19 -#define LM63_REG_REMOTE_TCRIT_HYST 0x21 - -#define LM63_REG_ALERT_STATUS 0x02 -#define LM63_REG_ALERT_MASK 0x16 - -#define LM63_REG_MAN_ID 0xFE -#define LM63_REG_CHIP_ID 0xFF - -#define LM96163_REG_TRUTHERM 0x30 -#define LM96163_REG_REMOTE_TEMP_U_MSB 0x31 -#define LM96163_REG_REMOTE_TEMP_U_LSB 0x32 -#define LM96163_REG_CONFIG_ENHANCED 0x45 - -#define LM63_MAX_CONVRATE 9 - -#define LM63_MAX_CONVRATE_HZ 32 -#define LM96163_MAX_CONVRATE_HZ 26 - -/* - * Conversions and various macros - * For tachometer counts, the LM63 uses 16-bit values. - * For local temperature and high limit, remote critical limit and hysteresis - * value, it uses signed 8-bit values with LSB = 1 degree Celsius. - * For remote temperature, low and high limits, it uses signed 11-bit values - * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers. - * For LM64 the actual remote diode temperature is 16 degree Celsius higher - * than the register reading. Remote temperature setpoints have to be - * adapted accordingly. - */ - -#define FAN_FROM_REG(reg) ((reg) == 0xFFFC || (reg) == 0 ? 0 : \ - 5400000 / (reg)) -#define FAN_TO_REG(val) ((val) <= 82 ? 0xFFFC : \ - (5400000 / (val)) & 0xFFFC) -#define TEMP8_FROM_REG(reg) ((reg) * 1000) -#define TEMP8_TO_REG(val) ((val) <= -128000 ? -128 : \ - (val) >= 127000 ? 127 : \ - (val) < 0 ? ((val) - 500) / 1000 : \ - ((val) + 500) / 1000) -#define TEMP8U_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 255000 ? 255 : \ - ((val) + 500) / 1000) -#define TEMP11_FROM_REG(reg) ((reg) / 32 * 125) -#define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ - (val) >= 127875 ? 0x7FE0 : \ - (val) < 0 ? ((val) - 62) / 125 * 32 : \ - ((val) + 62) / 125 * 32) -#define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 255875 ? 0xFFE0 : \ - ((val) + 62) / 125 * 32) -#define HYST_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 127000 ? 127 : \ - ((val) + 500) / 1000) - -#define UPDATE_INTERVAL(max, rate) \ - ((1000 << (LM63_MAX_CONVRATE - (rate))) / (max)) - -enum chips { lm63, lm64, lm96163 }; - -/* - * Client data (each client gets its own) - */ - -struct lm63_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - char lut_valid; /* zero until lut fields are valid */ - unsigned long last_updated; /* in jiffies */ - unsigned long lut_last_updated; /* in jiffies */ - enum chips kind; - int temp2_offset; - - int update_interval; /* in milliseconds */ - int max_convrate_hz; - int lut_size; /* 8 or 12 */ - - /* registers values */ - u8 config, config_fan; - u16 fan[2]; /* 0: input - 1: low limit */ - u8 pwm1_freq; - u8 pwm1[13]; /* 0: current output - 1-12: lookup table */ - s8 temp8[15]; /* 0: local input - 1: local high limit - 2: remote critical limit - 3-14: lookup table */ - s16 temp11[4]; /* 0: remote input - 1: remote low limit - 2: remote high limit - 3: remote offset */ - u16 temp11u; /* remote input (unsigned) */ - u8 temp2_crit_hyst; - u8 lut_temp_hyst; - u8 alarms; - bool pwm_highres; - bool lut_temp_highres; - bool remote_unsigned; /* true if unsigned remote upper limits */ - bool trutherm; -}; - -static inline int temp8_from_reg(struct lm63_data *data, int nr) -{ - if (data->remote_unsigned) - return TEMP8_FROM_REG((u8)data->temp8[nr]); - return TEMP8_FROM_REG(data->temp8[nr]); -} - -static inline int lut_temp_from_reg(struct lm63_data *data, int nr) -{ - return data->temp8[nr] * (data->lut_temp_highres ? 500 : 1000); -} - -static inline int lut_temp_to_reg(struct lm63_data *data, long val) -{ - val -= data->temp2_offset; - if (data->lut_temp_highres) - return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127500), 500); - else - return DIV_ROUND_CLOSEST(SENSORS_LIMIT(val, 0, 127000), 1000); -} - -/* - * Update the lookup table register cache. - * client->update_lock must be held when calling this function. - */ -static void lm63_update_lut(struct i2c_client *client) -{ - struct lm63_data *data = i2c_get_clientdata(client); - int i; - - if (time_after(jiffies, data->lut_last_updated + 5 * HZ) || - !data->lut_valid) { - for (i = 0; i < data->lut_size; i++) { - data->pwm1[1 + i] = i2c_smbus_read_byte_data(client, - LM63_REG_LUT_PWM(i)); - data->temp8[3 + i] = i2c_smbus_read_byte_data(client, - LM63_REG_LUT_TEMP(i)); - } - data->lut_temp_hyst = i2c_smbus_read_byte_data(client, - LM63_REG_LUT_TEMP_HYST); - - data->lut_last_updated = jiffies; - data->lut_valid = 1; - } -} - -static struct lm63_data *lm63_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - unsigned long next_update; - - mutex_lock(&data->update_lock); - - next_update = data->last_updated - + msecs_to_jiffies(data->update_interval) + 1; - - if (time_after(jiffies, next_update) || !data->valid) { - if (data->config & 0x04) { /* tachometer enabled */ - /* order matters for fan1_input */ - data->fan[0] = i2c_smbus_read_byte_data(client, - LM63_REG_TACH_COUNT_LSB) & 0xFC; - data->fan[0] |= i2c_smbus_read_byte_data(client, - LM63_REG_TACH_COUNT_MSB) << 8; - data->fan[1] = (i2c_smbus_read_byte_data(client, - LM63_REG_TACH_LIMIT_LSB) & 0xFC) - | (i2c_smbus_read_byte_data(client, - LM63_REG_TACH_LIMIT_MSB) << 8); - } - - data->pwm1_freq = i2c_smbus_read_byte_data(client, - LM63_REG_PWM_FREQ); - if (data->pwm1_freq == 0) - data->pwm1_freq = 1; - data->pwm1[0] = i2c_smbus_read_byte_data(client, - LM63_REG_PWM_VALUE); - - data->temp8[0] = i2c_smbus_read_byte_data(client, - LM63_REG_LOCAL_TEMP); - data->temp8[1] = i2c_smbus_read_byte_data(client, - LM63_REG_LOCAL_HIGH); - - /* order matters for temp2_input */ - data->temp11[0] = i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_TEMP_MSB) << 8; - data->temp11[0] |= i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_TEMP_LSB); - data->temp11[1] = (i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_LOW_MSB) << 8) - | i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_LOW_LSB); - data->temp11[2] = (i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_HIGH_MSB) << 8) - | i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_HIGH_LSB); - data->temp11[3] = (i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_OFFSET_MSB) << 8) - | i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_OFFSET_LSB); - - if (data->kind == lm96163) - data->temp11u = (i2c_smbus_read_byte_data(client, - LM96163_REG_REMOTE_TEMP_U_MSB) << 8) - | i2c_smbus_read_byte_data(client, - LM96163_REG_REMOTE_TEMP_U_LSB); - - data->temp8[2] = i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_TCRIT); - data->temp2_crit_hyst = i2c_smbus_read_byte_data(client, - LM63_REG_REMOTE_TCRIT_HYST); - - data->alarms = i2c_smbus_read_byte_data(client, - LM63_REG_ALERT_STATUS) & 0x7F; - - data->last_updated = jiffies; - data->valid = 1; - } - - lm63_update_lut(client); - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Trip points in the lookup table should be in ascending order for both - * temperatures and PWM output values. - */ -static int lm63_lut_looks_bad(struct i2c_client *client) -{ - struct lm63_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - lm63_update_lut(client); - - for (i = 1; i < data->lut_size; i++) { - if (data->pwm1[1 + i - 1] > data->pwm1[1 + i] - || data->temp8[3 + i - 1] > data->temp8[3 + i]) { - dev_warn(&client->dev, - "Lookup table doesn't look sane (check entries %d and %d)\n", - i, i + 1); - break; - } - } - mutex_unlock(&data->update_lock); - - return i == data->lut_size ? 0 : 1; -} - -/* - * Sysfs callback functions and files - */ - -static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index])); -} - -static ssize_t set_fan(struct device *dev, struct device_attribute *dummy, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan[1] = FAN_TO_REG(val); - i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_LSB, - data->fan[1] & 0xFF); - i2c_smbus_write_byte_data(client, LM63_REG_TACH_LIMIT_MSB, - data->fan[1] >> 8); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm1(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - int nr = attr->index; - int pwm; - - if (data->pwm_highres) - pwm = data->pwm1[nr]; - else - pwm = data->pwm1[nr] >= 2 * data->pwm1_freq ? - 255 : (data->pwm1[nr] * 255 + data->pwm1_freq) / - (2 * data->pwm1_freq); - - return sprintf(buf, "%d\n", pwm); -} - -static ssize_t set_pwm1(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - int nr = attr->index; - unsigned long val; - int err; - u8 reg; - - if (!(data->config_fan & 0x20)) /* register is read-only */ - return -EPERM; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - reg = nr ? LM63_REG_LUT_PWM(nr - 1) : LM63_REG_PWM_VALUE; - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - data->pwm1[nr] = data->pwm_highres ? val : - (val * data->pwm1_freq * 2 + 127) / 255; - i2c_smbus_write_byte_data(client, reg, data->pwm1[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm1_enable(struct device *dev, - struct device_attribute *dummy, char *buf) -{ - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%d\n", data->config_fan & 0x20 ? 1 : 2); -} - -static ssize_t set_pwm1_enable(struct device *dev, - struct device_attribute *dummy, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - if (val < 1 || val > 2) - return -EINVAL; - - /* - * Only let the user switch to automatic mode if the lookup table - * looks sane. - */ - if (val == 2 && lm63_lut_looks_bad(client)) - return -EPERM; - - mutex_lock(&data->update_lock); - data->config_fan = i2c_smbus_read_byte_data(client, - LM63_REG_CONFIG_FAN); - if (val == 1) - data->config_fan |= 0x20; - else - data->config_fan &= ~0x20; - i2c_smbus_write_byte_data(client, LM63_REG_CONFIG_FAN, - data->config_fan); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * There are 8bit registers for both local(temp1) and remote(temp2) sensor. - * For remote sensor registers temp2_offset has to be considered, - * for local sensor it must not. - * So we need separate 8bit accessors for local and remote sensor. - */ -static ssize_t show_local_temp8(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%d\n", TEMP8_FROM_REG(data->temp8[attr->index])); -} - -static ssize_t show_remote_temp8(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%d\n", temp8_from_reg(data, attr->index) - + data->temp2_offset); -} - -static ssize_t show_lut_temp(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index) - + data->temp2_offset); -} - -static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - int nr = attr->index; - long val; - int err; - int temp; - u8 reg; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (nr) { - case 2: - reg = LM63_REG_REMOTE_TCRIT; - if (data->remote_unsigned) - temp = TEMP8U_TO_REG(val - data->temp2_offset); - else - temp = TEMP8_TO_REG(val - data->temp2_offset); - break; - case 1: - reg = LM63_REG_LOCAL_HIGH; - temp = TEMP8_TO_REG(val); - break; - default: /* lookup table */ - reg = LM63_REG_LUT_TEMP(nr - 3); - temp = lut_temp_to_reg(data, val); - } - data->temp8[nr] = temp; - i2c_smbus_write_byte_data(client, reg, temp); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - int nr = attr->index; - int temp; - - if (!nr) { - /* - * Use unsigned temperature unless its value is zero. - * If it is zero, use signed temperature. - */ - if (data->temp11u) - temp = TEMP11_FROM_REG(data->temp11u); - else - temp = TEMP11_FROM_REG(data->temp11[nr]); - } else { - if (data->remote_unsigned && nr == 2) - temp = TEMP11_FROM_REG((u16)data->temp11[nr]); - else - temp = TEMP11_FROM_REG(data->temp11[nr]); - } - return sprintf(buf, "%d\n", temp + data->temp2_offset); -} - -static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - static const u8 reg[6] = { - LM63_REG_REMOTE_LOW_MSB, - LM63_REG_REMOTE_LOW_LSB, - LM63_REG_REMOTE_HIGH_MSB, - LM63_REG_REMOTE_HIGH_LSB, - LM63_REG_REMOTE_OFFSET_MSB, - LM63_REG_REMOTE_OFFSET_LSB, - }; - - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - long val; - int err; - int nr = attr->index; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (data->remote_unsigned && nr == 2) - data->temp11[nr] = TEMP11U_TO_REG(val - data->temp2_offset); - else - data->temp11[nr] = TEMP11_TO_REG(val - data->temp2_offset); - - i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2], - data->temp11[nr] >> 8); - i2c_smbus_write_byte_data(client, reg[(nr - 1) * 2 + 1], - data->temp11[nr] & 0xff); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Hysteresis register holds a relative value, while we want to present - * an absolute to user-space - */ -static ssize_t show_temp2_crit_hyst(struct device *dev, - struct device_attribute *dummy, char *buf) -{ - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%d\n", temp8_from_reg(data, 2) - + data->temp2_offset - - TEMP8_FROM_REG(data->temp2_crit_hyst)); -} - -static ssize_t show_lut_temp_hyst(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - - return sprintf(buf, "%d\n", lut_temp_from_reg(data, attr->index) - + data->temp2_offset - - TEMP8_FROM_REG(data->lut_temp_hyst)); -} - -/* - * And now the other way around, user-space provides an absolute - * hysteresis value and we have to store a relative one - */ -static ssize_t set_temp2_crit_hyst(struct device *dev, - struct device_attribute *dummy, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - long val; - int err; - long hyst; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - hyst = temp8_from_reg(data, 2) + data->temp2_offset - val; - i2c_smbus_write_byte_data(client, LM63_REG_REMOTE_TCRIT_HYST, - HYST_TO_REG(hyst)); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Set conversion rate. - * client->update_lock must be held when calling this function. - */ -static void lm63_set_convrate(struct i2c_client *client, struct lm63_data *data, - unsigned int interval) -{ - int i; - unsigned int update_interval; - - /* Shift calculations to avoid rounding errors */ - interval <<= 6; - - /* find the nearest update rate */ - update_interval = (1 << (LM63_MAX_CONVRATE + 6)) * 1000 - / data->max_convrate_hz; - for (i = 0; i < LM63_MAX_CONVRATE; i++, update_interval >>= 1) - if (interval >= update_interval * 3 / 4) - break; - - i2c_smbus_write_byte_data(client, LM63_REG_CONVRATE, i); - data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, i); -} - -static ssize_t show_update_interval(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm63_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", data->update_interval); -} - -static ssize_t set_update_interval(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - lm63_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000)); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_type(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - - return sprintf(buf, data->trutherm ? "1\n" : "2\n"); -} - -static ssize_t set_type(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - unsigned long val; - int ret; - u8 reg; - - ret = kstrtoul(buf, 10, &val); - if (ret < 0) - return ret; - if (val != 1 && val != 2) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->trutherm = val == 1; - reg = i2c_smbus_read_byte_data(client, LM96163_REG_TRUTHERM) & ~0x02; - i2c_smbus_write_byte_data(client, LM96163_REG_TRUTHERM, - reg | (data->trutherm ? 0x02 : 0x00)); - data->valid = 0; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, - char *buf) -{ - struct lm63_data *data = lm63_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm63_data *data = lm63_update_device(dev); - int bitnr = attr->index; - - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, - set_fan, 1); - -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm1, set_pwm1, 0); -static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - show_pwm1_enable, set_pwm1_enable); -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 1); -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 3); -static SENSOR_DEVICE_ATTR(pwm1_auto_point1_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 3); -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 2); -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 4); -static SENSOR_DEVICE_ATTR(pwm1_auto_point2_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 4); -static SENSOR_DEVICE_ATTR(pwm1_auto_point3_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 3); -static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 5); -static SENSOR_DEVICE_ATTR(pwm1_auto_point3_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 5); -static SENSOR_DEVICE_ATTR(pwm1_auto_point4_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 4); -static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 6); -static SENSOR_DEVICE_ATTR(pwm1_auto_point4_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 6); -static SENSOR_DEVICE_ATTR(pwm1_auto_point5_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 5); -static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 7); -static SENSOR_DEVICE_ATTR(pwm1_auto_point5_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 7); -static SENSOR_DEVICE_ATTR(pwm1_auto_point6_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 6); -static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 8); -static SENSOR_DEVICE_ATTR(pwm1_auto_point6_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 8); -static SENSOR_DEVICE_ATTR(pwm1_auto_point7_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 7); -static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 9); -static SENSOR_DEVICE_ATTR(pwm1_auto_point7_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 9); -static SENSOR_DEVICE_ATTR(pwm1_auto_point8_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 8); -static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 10); -static SENSOR_DEVICE_ATTR(pwm1_auto_point8_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 10); -static SENSOR_DEVICE_ATTR(pwm1_auto_point9_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 9); -static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 11); -static SENSOR_DEVICE_ATTR(pwm1_auto_point9_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 11); -static SENSOR_DEVICE_ATTR(pwm1_auto_point10_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 10); -static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 12); -static SENSOR_DEVICE_ATTR(pwm1_auto_point10_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 12); -static SENSOR_DEVICE_ATTR(pwm1_auto_point11_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 11); -static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 13); -static SENSOR_DEVICE_ATTR(pwm1_auto_point11_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 13); -static SENSOR_DEVICE_ATTR(pwm1_auto_point12_pwm, S_IWUSR | S_IRUGO, - show_pwm1, set_pwm1, 12); -static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp, S_IWUSR | S_IRUGO, - show_lut_temp, set_temp8, 14); -static SENSOR_DEVICE_ATTR(pwm1_auto_point12_temp_hyst, S_IRUGO, - show_lut_temp_hyst, NULL, 14); - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_local_temp8, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_local_temp8, - set_temp8, 1); - -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp11, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 2); -static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 3); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_remote_temp8, - set_temp8, 2); -static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, - set_temp2_crit_hyst); - -static DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type); - -/* Individual alarm files */ -static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -/* Raw alarm file for compatibility */ -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, - set_update_interval); - -static struct attribute *lm63_attributes[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &dev_attr_pwm1_enable.attr, - &sensor_dev_attr_pwm1_auto_point1_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point1_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point2_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point3_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point4_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point4_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point4_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point5_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point5_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point5_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point6_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point6_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point6_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point7_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point7_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point7_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point8_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point8_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point8_temp_hyst.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &dev_attr_temp2_crit_hyst.attr, - - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_update_interval.attr, - NULL -}; - -static struct attribute *lm63_attributes_extra_lut[] = { - &sensor_dev_attr_pwm1_auto_point9_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point9_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point9_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point10_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point10_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point10_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point11_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point11_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point11_temp_hyst.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point12_pwm.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point12_temp.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_point12_temp_hyst.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm63_group_extra_lut = { - .attrs = lm63_attributes_extra_lut, -}; - -/* - * On LM63, temp2_crit can be set only once, which should be job - * of the bootloader. - * On LM64, temp2_crit can always be set. - * On LM96163, temp2_crit can be set if bit 1 of the configuration - * register is true. - */ -static umode_t lm63_attribute_mode(struct kobject *kobj, - struct attribute *attr, int index) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct i2c_client *client = to_i2c_client(dev); - struct lm63_data *data = i2c_get_clientdata(client); - - if (attr == &sensor_dev_attr_temp2_crit.dev_attr.attr - && (data->kind == lm64 || - (data->kind == lm96163 && (data->config & 0x02)))) - return attr->mode | S_IWUSR; - - return attr->mode; -} - -static const struct attribute_group lm63_group = { - .is_visible = lm63_attribute_mode, - .attrs = lm63_attributes, -}; - -static struct attribute *lm63_attributes_fan1[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - - &sensor_dev_attr_fan1_min_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm63_group_fan1 = { - .attrs = lm63_attributes_fan1, -}; - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm63_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u8 man_id, chip_id, reg_config1, reg_config2; - u8 reg_alert_status, reg_alert_mask; - int address = client->addr; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - man_id = i2c_smbus_read_byte_data(client, LM63_REG_MAN_ID); - chip_id = i2c_smbus_read_byte_data(client, LM63_REG_CHIP_ID); - - reg_config1 = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1); - reg_config2 = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG2); - reg_alert_status = i2c_smbus_read_byte_data(client, - LM63_REG_ALERT_STATUS); - reg_alert_mask = i2c_smbus_read_byte_data(client, LM63_REG_ALERT_MASK); - - if (man_id != 0x01 /* National Semiconductor */ - || (reg_config1 & 0x18) != 0x00 - || (reg_config2 & 0xF8) != 0x00 - || (reg_alert_status & 0x20) != 0x00 - || (reg_alert_mask & 0xA4) != 0xA4) { - dev_dbg(&adapter->dev, - "Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n", - man_id, chip_id); - return -ENODEV; - } - - if (chip_id == 0x41 && address == 0x4c) - strlcpy(info->type, "lm63", I2C_NAME_SIZE); - else if (chip_id == 0x51 && (address == 0x18 || address == 0x4e)) - strlcpy(info->type, "lm64", I2C_NAME_SIZE); - else if (chip_id == 0x49 && address == 0x4c) - strlcpy(info->type, "lm96163", I2C_NAME_SIZE); - else - return -ENODEV; - - return 0; -} - -/* - * Ideally we shouldn't have to initialize anything, since the BIOS - * should have taken care of everything - */ -static void lm63_init_client(struct i2c_client *client) -{ - struct lm63_data *data = i2c_get_clientdata(client); - u8 convrate; - - data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1); - data->config_fan = i2c_smbus_read_byte_data(client, - LM63_REG_CONFIG_FAN); - - /* Start converting if needed */ - if (data->config & 0x40) { /* standby */ - dev_dbg(&client->dev, "Switching to operational mode\n"); - data->config &= 0xA7; - i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1, - data->config); - } - /* Tachometer is always enabled on LM64 */ - if (data->kind == lm64) - data->config |= 0x04; - - /* We may need pwm1_freq before ever updating the client data */ - data->pwm1_freq = i2c_smbus_read_byte_data(client, LM63_REG_PWM_FREQ); - if (data->pwm1_freq == 0) - data->pwm1_freq = 1; - - switch (data->kind) { - case lm63: - case lm64: - data->max_convrate_hz = LM63_MAX_CONVRATE_HZ; - data->lut_size = 8; - break; - case lm96163: - data->max_convrate_hz = LM96163_MAX_CONVRATE_HZ; - data->lut_size = 12; - data->trutherm - = i2c_smbus_read_byte_data(client, - LM96163_REG_TRUTHERM) & 0x02; - break; - } - convrate = i2c_smbus_read_byte_data(client, LM63_REG_CONVRATE); - if (unlikely(convrate > LM63_MAX_CONVRATE)) - convrate = LM63_MAX_CONVRATE; - data->update_interval = UPDATE_INTERVAL(data->max_convrate_hz, - convrate); - - /* - * For LM96163, check if high resolution PWM - * and unsigned temperature format is enabled. - */ - if (data->kind == lm96163) { - u8 config_enhanced - = i2c_smbus_read_byte_data(client, - LM96163_REG_CONFIG_ENHANCED); - if (config_enhanced & 0x20) - data->lut_temp_highres = true; - if ((config_enhanced & 0x10) - && !(data->config_fan & 0x08) && data->pwm1_freq == 8) - data->pwm_highres = true; - if (config_enhanced & 0x08) - data->remote_unsigned = true; - } - - /* Show some debug info about the LM63 configuration */ - if (data->kind == lm63) - dev_dbg(&client->dev, "Alert/tach pin configured for %s\n", - (data->config & 0x04) ? "tachometer input" : - "alert output"); - dev_dbg(&client->dev, "PWM clock %s kHz, output frequency %u Hz\n", - (data->config_fan & 0x08) ? "1.4" : "360", - ((data->config_fan & 0x08) ? 700 : 180000) / data->pwm1_freq); - dev_dbg(&client->dev, "PWM output active %s, %s mode\n", - (data->config_fan & 0x10) ? "low" : "high", - (data->config_fan & 0x20) ? "manual" : "auto"); -} - -static int lm63_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm63_data *data; - int err; - - data = kzalloc(sizeof(struct lm63_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Set the device type */ - data->kind = id->driver_data; - if (data->kind == lm64) - data->temp2_offset = 16000; - - /* Initialize chip */ - lm63_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm63_group); - if (err) - goto exit_free; - if (data->config & 0x04) { /* tachometer enabled */ - err = sysfs_create_group(&client->dev.kobj, &lm63_group_fan1); - if (err) - goto exit_remove_files; - } - if (data->kind == lm96163) { - err = device_create_file(&client->dev, &dev_attr_temp2_type); - if (err) - goto exit_remove_files; - - err = sysfs_create_group(&client->dev.kobj, - &lm63_group_extra_lut); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &lm63_group); - sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); - if (data->kind == lm96163) { - device_remove_file(&client->dev, &dev_attr_temp2_type); - sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut); - } -exit_free: - kfree(data); -exit: - return err; -} - -static int lm63_remove(struct i2c_client *client) -{ - struct lm63_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm63_group); - sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); - if (data->kind == lm96163) { - device_remove_file(&client->dev, &dev_attr_temp2_type); - sysfs_remove_group(&client->dev.kobj, &lm63_group_extra_lut); - } - - kfree(data); - return 0; -} - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id lm63_id[] = { - { "lm63", lm63 }, - { "lm64", lm64 }, - { "lm96163", lm96163 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm63_id); - -static struct i2c_driver lm63_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm63", - }, - .probe = lm63_probe, - .remove = lm63_remove, - .id_table = lm63_id, - .detect = lm63_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm63_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("LM63 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm70.c b/ANDROID_3.4.5/drivers/hwmon/lm70.c deleted file mode 100644 index 472f7952..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm70.c +++ /dev/null @@ -1,223 +0,0 @@ -/* - * lm70.c - * - * The LM70 is a temperature sensor chip from National Semiconductor (NS). - * Copyright (C) 2006 Kaiwan N Billimoria - * - * The LM70 communicates with a host processor via an SPI/Microwire Bus - * interface. The complete datasheet is available at National's website - * here: - * http://www.national.com/pf/LM/LM70.html - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#define DRVNAME "lm70" - -#define LM70_CHIP_LM70 0 /* original NS LM70 */ -#define LM70_CHIP_TMP121 1 /* TI TMP121/TMP123 */ - -struct lm70 { - struct device *hwmon_dev; - struct mutex lock; - unsigned int chip; -}; - -/* sysfs hook function */ -static ssize_t lm70_sense_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct spi_device *spi = to_spi_device(dev); - int status, val = 0; - u8 rxbuf[2]; - s16 raw = 0; - struct lm70 *p_lm70 = spi_get_drvdata(spi); - - if (mutex_lock_interruptible(&p_lm70->lock)) - return -ERESTARTSYS; - - /* - * spi_read() requires a DMA-safe buffer; so we use - * spi_write_then_read(), transmitting 0 bytes. - */ - status = spi_write_then_read(spi, NULL, 0, &rxbuf[0], 2); - if (status < 0) { - pr_warn("spi_write_then_read failed with status %d\n", status); - goto out; - } - raw = (rxbuf[0] << 8) + rxbuf[1]; - dev_dbg(dev, "rxbuf[0] : 0x%02x rxbuf[1] : 0x%02x raw=0x%04x\n", - rxbuf[0], rxbuf[1], raw); - - /* - * LM70: - * The "raw" temperature read into rxbuf[] is a 16-bit signed 2's - * complement value. Only the MSB 11 bits (1 sign + 10 temperature - * bits) are meaningful; the LSB 5 bits are to be discarded. - * See the datasheet. - * - * Further, each bit represents 0.25 degrees Celsius; so, multiply - * by 0.25. Also multiply by 1000 to represent in millidegrees - * Celsius. - * So it's equivalent to multiplying by 0.25 * 1000 = 250. - * - * TMP121/TMP123: - * 13 bits of 2's complement data, discard LSB 3 bits, - * resolution 0.0625 degrees celsius. - */ - switch (p_lm70->chip) { - case LM70_CHIP_LM70: - val = ((int)raw / 32) * 250; - break; - - case LM70_CHIP_TMP121: - val = ((int)raw / 8) * 625 / 10; - break; - } - - status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ -out: - mutex_unlock(&p_lm70->lock); - return status; -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); - -static ssize_t lm70_show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct lm70 *p_lm70 = dev_get_drvdata(dev); - int ret; - - switch (p_lm70->chip) { - case LM70_CHIP_LM70: - ret = sprintf(buf, "lm70\n"); - break; - case LM70_CHIP_TMP121: - ret = sprintf(buf, "tmp121\n"); - break; - default: - ret = -EINVAL; - } - return ret; -} - -static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); - -/*----------------------------------------------------------------------*/ - -static int __devinit lm70_probe(struct spi_device *spi) -{ - int chip = spi_get_device_id(spi)->driver_data; - struct lm70 *p_lm70; - int status; - - /* signaling is SPI_MODE_0 for both LM70 and TMP121 */ - if (spi->mode & (SPI_CPOL | SPI_CPHA)) - return -EINVAL; - - /* 3-wire link (shared SI/SO) for LM70 */ - if (chip == LM70_CHIP_LM70 && !(spi->mode & SPI_3WIRE)) - return -EINVAL; - - /* NOTE: we assume 8-bit words, and convert to 16 bits manually */ - - p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); - if (!p_lm70) - return -ENOMEM; - - mutex_init(&p_lm70->lock); - p_lm70->chip = chip; - - spi_set_drvdata(spi, p_lm70); - - status = device_create_file(&spi->dev, &dev_attr_temp1_input); - if (status) - goto out_dev_create_temp_file_failed; - status = device_create_file(&spi->dev, &dev_attr_name); - if (status) - goto out_dev_create_file_failed; - - /* sysfs hook */ - p_lm70->hwmon_dev = hwmon_device_register(&spi->dev); - if (IS_ERR(p_lm70->hwmon_dev)) { - dev_dbg(&spi->dev, "hwmon_device_register failed.\n"); - status = PTR_ERR(p_lm70->hwmon_dev); - goto out_dev_reg_failed; - } - - return 0; - -out_dev_reg_failed: - device_remove_file(&spi->dev, &dev_attr_name); -out_dev_create_file_failed: - device_remove_file(&spi->dev, &dev_attr_temp1_input); -out_dev_create_temp_file_failed: - spi_set_drvdata(spi, NULL); - kfree(p_lm70); - return status; -} - -static int __devexit lm70_remove(struct spi_device *spi) -{ - struct lm70 *p_lm70 = spi_get_drvdata(spi); - - hwmon_device_unregister(p_lm70->hwmon_dev); - device_remove_file(&spi->dev, &dev_attr_temp1_input); - device_remove_file(&spi->dev, &dev_attr_name); - spi_set_drvdata(spi, NULL); - kfree(p_lm70); - - return 0; -} - - -static const struct spi_device_id lm70_ids[] = { - { "lm70", LM70_CHIP_LM70 }, - { "tmp121", LM70_CHIP_TMP121 }, - { }, -}; -MODULE_DEVICE_TABLE(spi, lm70_ids); - -static struct spi_driver lm70_driver = { - .driver = { - .name = "lm70", - .owner = THIS_MODULE, - }, - .id_table = lm70_ids, - .probe = lm70_probe, - .remove = __devexit_p(lm70_remove), -}; - -module_spi_driver(lm70_driver); - -MODULE_AUTHOR("Kaiwan N Billimoria"); -MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm73.c b/ANDROID_3.4.5/drivers/hwmon/lm73.c deleted file mode 100644 index 8fa2632c..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm73.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * LM73 Sensor driver - * Based on LM75 - * - * Copyright (C) 2007, CenoSYS (www.cenosys.com). - * Copyright (C) 2009, Bollore telecom (www.bolloretelecom.eu). - * - * Guillaume Ligneul - * Adrien Demarez - * Jeremy Laine - * - * This software program is licensed subject to the GNU General Public License - * (GPL).Version 2,June 1991, available at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html - */ - -#include -#include -#include -#include -#include -#include - - -/* Addresses scanned */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4c, - 0x4d, 0x4e, I2C_CLIENT_END }; - -/* LM73 registers */ -#define LM73_REG_INPUT 0x00 -#define LM73_REG_CONF 0x01 -#define LM73_REG_MAX 0x02 -#define LM73_REG_MIN 0x03 -#define LM73_REG_CTRL 0x04 -#define LM73_REG_ID 0x07 - -#define LM73_ID 0x9001 /* 0x0190, byte-swapped */ -#define DRVNAME "lm73" -#define LM73_TEMP_MIN (-40) -#define LM73_TEMP_MAX 150 - -/*-----------------------------------------------------------------------*/ - - -static ssize_t set_temp(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - long temp; - short value; - - int status = kstrtol(buf, 10, &temp); - if (status < 0) - return status; - - /* Write value */ - value = (short) SENSORS_LIMIT(temp/250, (LM73_TEMP_MIN*4), - (LM73_TEMP_MAX*4)) << 5; - i2c_smbus_write_word_swapped(client, attr->index, value); - return count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - /* use integer division instead of equivalent right shift to - guarantee arithmetic shift and preserve the sign */ - int temp = ((s16) (i2c_smbus_read_word_swapped(client, - attr->index))*250) / 32; - return sprintf(buf, "%d\n", temp); -} - - -/*-----------------------------------------------------------------------*/ - -/* sysfs attributes for hwmon */ - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp, set_temp, LM73_REG_MAX); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - show_temp, set_temp, LM73_REG_MIN); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - show_temp, NULL, LM73_REG_INPUT); - - -static struct attribute *lm73_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - - NULL -}; - -static const struct attribute_group lm73_group = { - .attrs = lm73_attributes, -}; - -/*-----------------------------------------------------------------------*/ - -/* device probe and removal */ - -static int -lm73_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct device *hwmon_dev; - int status; - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &lm73_group); - if (status) - return status; - - hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(hwmon_dev)) { - status = PTR_ERR(hwmon_dev); - goto exit_remove; - } - i2c_set_clientdata(client, hwmon_dev); - - dev_info(&client->dev, "%s: sensor '%s'\n", - dev_name(hwmon_dev), client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &lm73_group); - return status; -} - -static int lm73_remove(struct i2c_client *client) -{ - struct device *hwmon_dev = i2c_get_clientdata(client); - - hwmon_device_unregister(hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm73_group); - return 0; -} - -static const struct i2c_device_id lm73_ids[] = { - { "lm73", 0 }, - { /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, lm73_ids); - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm73_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - int id, ctrl, conf; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - /* - * Do as much detection as possible with byte reads first, as word - * reads can confuse other devices. - */ - ctrl = i2c_smbus_read_byte_data(new_client, LM73_REG_CTRL); - if (ctrl < 0 || (ctrl & 0x10)) - return -ENODEV; - - conf = i2c_smbus_read_byte_data(new_client, LM73_REG_CONF); - if (conf < 0 || (conf & 0x0c)) - return -ENODEV; - - id = i2c_smbus_read_byte_data(new_client, LM73_REG_ID); - if (id < 0 || id != (LM73_ID & 0xff)) - return -ENODEV; - - /* Check device ID */ - id = i2c_smbus_read_word_data(new_client, LM73_REG_ID); - if (id < 0 || id != LM73_ID) - return -ENODEV; - - strlcpy(info->type, "lm73", I2C_NAME_SIZE); - - return 0; -} - -static struct i2c_driver lm73_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm73", - }, - .probe = lm73_probe, - .remove = lm73_remove, - .id_table = lm73_ids, - .detect = lm73_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm73_driver); - -MODULE_AUTHOR("Guillaume Ligneul "); -MODULE_DESCRIPTION("LM73 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm75.c b/ANDROID_3.4.5/drivers/hwmon/lm75.c deleted file mode 100644 index a83f206a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm75.c +++ /dev/null @@ -1,445 +0,0 @@ -/* - * lm75.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998, 1999 Frodo Looijaard - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lm75.h" - - -/* - * This driver handles the LM75 and compatible digital temperature sensors. - */ - -enum lm75_type { /* keep sorted in alphabetical order */ - adt75, - ds1775, - ds75, - lm75, - lm75a, - max6625, - max6626, - mcp980x, - stds75, - tcn75, - tmp100, - tmp101, - tmp105, - tmp175, - tmp275, - tmp75, -}; - -/* Addresses scanned */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, 0x4c, - 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; - - -/* The LM75 registers */ -#define LM75_REG_CONF 0x01 -static const u8 LM75_REG_TEMP[3] = { - 0x00, /* input */ - 0x03, /* max */ - 0x02, /* hyst */ -}; - -/* Each client has this additional data */ -struct lm75_data { - struct device *hwmon_dev; - struct mutex update_lock; - u8 orig_conf; - char valid; /* !=0 if registers are valid */ - unsigned long last_updated; /* In jiffies */ - u16 temp[3]; /* Register values, - 0 = input - 1 = max - 2 = hyst */ -}; - -static int lm75_read_value(struct i2c_client *client, u8 reg); -static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value); -static struct lm75_data *lm75_update_device(struct device *dev); - - -/*-----------------------------------------------------------------------*/ - -/* sysfs attributes for hwmon */ - -static ssize_t show_temp(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm75_data *data = lm75_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", - LM75_TEMP_FROM_REG(data->temp[attr->index])); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct lm75_data *data = i2c_get_clientdata(client); - int nr = attr->index; - long temp; - int error; - - error = kstrtol(buf, 10, &temp); - if (error) - return error; - - mutex_lock(&data->update_lock); - data->temp[nr] = LM75_TEMP_TO_REG(temp); - lm75_write_value(client, LM75_REG_TEMP[nr], data->temp[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp, set_temp, 1); -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, - show_temp, set_temp, 2); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); - -static struct attribute *lm75_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - - NULL -}; - -static const struct attribute_group lm75_group = { - .attrs = lm75_attributes, -}; - -/*-----------------------------------------------------------------------*/ - -/* device probe and removal */ - -static int -lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct lm75_data *data; - int status; - u8 set_mask, clr_mask; - int new; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) - return -EIO; - - data = kzalloc(sizeof(struct lm75_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Set to LM75 resolution (9 bits, 1/2 degree C) and range. - * Then tweak to be more precise when appropriate. - */ - set_mask = 0; - clr_mask = (1 << 0) /* continuous conversions */ - | (1 << 6) | (1 << 5); /* 9-bit mode */ - - /* configure as specified */ - status = lm75_read_value(client, LM75_REG_CONF); - if (status < 0) { - dev_dbg(&client->dev, "Can't read config? %d\n", status); - goto exit_free; - } - data->orig_conf = status; - new = status & ~clr_mask; - new |= set_mask; - if (status != new) - lm75_write_value(client, LM75_REG_CONF, new); - dev_dbg(&client->dev, "Config %02x\n", new); - - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &lm75_group); - if (status) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "%s: sensor '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &lm75_group); -exit_free: - kfree(data); - return status; -} - -static int lm75_remove(struct i2c_client *client) -{ - struct lm75_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm75_group); - lm75_write_value(client, LM75_REG_CONF, data->orig_conf); - kfree(data); - return 0; -} - -static const struct i2c_device_id lm75_ids[] = { - { "adt75", adt75, }, - { "ds1775", ds1775, }, - { "ds75", ds75, }, - { "lm75", lm75, }, - { "lm75a", lm75a, }, - { "max6625", max6625, }, - { "max6626", max6626, }, - { "mcp980x", mcp980x, }, - { "stds75", stds75, }, - { "tcn75", tcn75, }, - { "tmp100", tmp100, }, - { "tmp101", tmp101, }, - { "tmp105", tmp105, }, - { "tmp175", tmp175, }, - { "tmp275", tmp275, }, - { "tmp75", tmp75, }, - { /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, lm75_ids); - -#define LM75A_ID 0xA1 - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm75_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - int i; - int conf, hyst, os; - bool is_lm75a = 0; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - /* - * Now, we do the remaining detection. There is no identification- - * dedicated register so we have to rely on several tricks: - * unused bits, registers cycling over 8-address boundaries, - * addresses 0x04-0x07 returning the last read value. - * The cycling+unused addresses combination is not tested, - * since it would significantly slow the detection down and would - * hardly add any value. - * - * The National Semiconductor LM75A is different than earlier - * LM75s. It has an ID byte of 0xaX (where X is the chip - * revision, with 1 being the only revision in existence) in - * register 7, and unused registers return 0xff rather than the - * last read value. - * - * Note that this function only detects the original National - * Semiconductor LM75 and the LM75A. Clones from other vendors - * aren't detected, on purpose, because they are typically never - * found on PC hardware. They are found on embedded designs where - * they can be instantiated explicitly so detection is not needed. - * The absence of identification registers on all these clones - * would make their exhaustive detection very difficult and weak, - * and odds are that the driver would bind to unsupported devices. - */ - - /* Unused bits */ - conf = i2c_smbus_read_byte_data(new_client, 1); - if (conf & 0xe0) - return -ENODEV; - - /* First check for LM75A */ - if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) { - /* LM75A returns 0xff on unused registers so - just to be sure we check for that too. */ - if (i2c_smbus_read_byte_data(new_client, 4) != 0xff - || i2c_smbus_read_byte_data(new_client, 5) != 0xff - || i2c_smbus_read_byte_data(new_client, 6) != 0xff) - return -ENODEV; - is_lm75a = 1; - hyst = i2c_smbus_read_byte_data(new_client, 2); - os = i2c_smbus_read_byte_data(new_client, 3); - } else { /* Traditional style LM75 detection */ - /* Unused addresses */ - hyst = i2c_smbus_read_byte_data(new_client, 2); - if (i2c_smbus_read_byte_data(new_client, 4) != hyst - || i2c_smbus_read_byte_data(new_client, 5) != hyst - || i2c_smbus_read_byte_data(new_client, 6) != hyst - || i2c_smbus_read_byte_data(new_client, 7) != hyst) - return -ENODEV; - os = i2c_smbus_read_byte_data(new_client, 3); - if (i2c_smbus_read_byte_data(new_client, 4) != os - || i2c_smbus_read_byte_data(new_client, 5) != os - || i2c_smbus_read_byte_data(new_client, 6) != os - || i2c_smbus_read_byte_data(new_client, 7) != os) - return -ENODEV; - } - - /* Addresses cycling */ - for (i = 8; i <= 248; i += 40) { - if (i2c_smbus_read_byte_data(new_client, i + 1) != conf - || i2c_smbus_read_byte_data(new_client, i + 2) != hyst - || i2c_smbus_read_byte_data(new_client, i + 3) != os) - return -ENODEV; - if (is_lm75a && i2c_smbus_read_byte_data(new_client, i + 7) - != LM75A_ID) - return -ENODEV; - } - - strlcpy(info->type, is_lm75a ? "lm75a" : "lm75", I2C_NAME_SIZE); - - return 0; -} - -#ifdef CONFIG_PM -static int lm75_suspend(struct device *dev) -{ - int status; - struct i2c_client *client = to_i2c_client(dev); - status = lm75_read_value(client, LM75_REG_CONF); - if (status < 0) { - dev_dbg(&client->dev, "Can't read config? %d\n", status); - return status; - } - status = status | LM75_SHUTDOWN; - lm75_write_value(client, LM75_REG_CONF, status); - return 0; -} - -static int lm75_resume(struct device *dev) -{ - int status; - struct i2c_client *client = to_i2c_client(dev); - status = lm75_read_value(client, LM75_REG_CONF); - if (status < 0) { - dev_dbg(&client->dev, "Can't read config? %d\n", status); - return status; - } - status = status & ~LM75_SHUTDOWN; - lm75_write_value(client, LM75_REG_CONF, status); - return 0; -} - -static const struct dev_pm_ops lm75_dev_pm_ops = { - .suspend = lm75_suspend, - .resume = lm75_resume, -}; -#define LM75_DEV_PM_OPS (&lm75_dev_pm_ops) -#else -#define LM75_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - -static struct i2c_driver lm75_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm75", - .pm = LM75_DEV_PM_OPS, - }, - .probe = lm75_probe, - .remove = lm75_remove, - .id_table = lm75_ids, - .detect = lm75_detect, - .address_list = normal_i2c, -}; - -/*-----------------------------------------------------------------------*/ - -/* register access */ - -/* - * All registers are word-sized, except for the configuration register. - * LM75 uses a high-byte first convention, which is exactly opposite to - * the SMBus standard. - */ -static int lm75_read_value(struct i2c_client *client, u8 reg) -{ - if (reg == LM75_REG_CONF) - return i2c_smbus_read_byte_data(client, reg); - else - return i2c_smbus_read_word_swapped(client, reg); -} - -static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if (reg == LM75_REG_CONF) - return i2c_smbus_write_byte_data(client, reg, value); - else - return i2c_smbus_write_word_swapped(client, reg, value); -} - -static struct lm75_data *lm75_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm75_data *data = i2c_get_clientdata(client); - struct lm75_data *ret = data; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - dev_dbg(&client->dev, "Starting lm75 update\n"); - - for (i = 0; i < ARRAY_SIZE(data->temp); i++) { - int status; - - status = lm75_read_value(client, LM75_REG_TEMP[i]); - if (unlikely(status < 0)) { - dev_dbg(dev, - "LM75: Failed to read value: reg %d, error %d\n", - LM75_REG_TEMP[i], status); - ret = ERR_PTR(status); - data->valid = 0; - goto abort; - } - data->temp[i] = status; - } - data->last_updated = jiffies; - data->valid = 1; - } - -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -module_i2c_driver(lm75_driver); - -MODULE_AUTHOR("Frodo Looijaard "); -MODULE_DESCRIPTION("LM75 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm75.h b/ANDROID_3.4.5/drivers/hwmon/lm75.h deleted file mode 100644 index 89aa9098..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm75.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - lm75.h - Part of lm_sensors, Linux kernel modules for hardware - monitoring - Copyright (c) 2003 Mark M. Hoffman - - 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. -*/ - -/* - This file contains common code for encoding/decoding LM75 type - temperature readings, which are emulated by many of the chips - we support. As the user is unlikely to load more than one driver - which contains this code, we don't worry about the wasted space. -*/ - -#include - -/* straight from the datasheet */ -#define LM75_TEMP_MIN (-55000) -#define LM75_TEMP_MAX 125000 -#define LM75_SHUTDOWN 0x01 - -/* TEMP: 0.001C/bit (-55C to +125C) - REG: (0.5C/bit, two's complement) << 7 */ -static inline u16 LM75_TEMP_TO_REG(long temp) -{ - int ntemp = SENSORS_LIMIT(temp, LM75_TEMP_MIN, LM75_TEMP_MAX); - ntemp += (ntemp < 0 ? -250 : 250); - return (u16)((ntemp / 500) << 7); -} - -static inline int LM75_TEMP_FROM_REG(u16 reg) -{ - /* use integer division instead of equivalent right shift to - guarantee arithmetic shift and preserve the sign */ - return ((s16)reg / 128) * 500; -} diff --git a/ANDROID_3.4.5/drivers/hwmon/lm77.c b/ANDROID_3.4.5/drivers/hwmon/lm77.c deleted file mode 100644 index 0fca8613..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm77.c +++ /dev/null @@ -1,458 +0,0 @@ -/* - * lm77.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * - * Copyright (c) 2004 Andras BALI - * - * Heavily based on lm75.c by Frodo Looijaard . The LM77 - * is a temperature sensor and thermal window comparator with 0.5 deg - * resolution made by National Semiconductor. Complete datasheet can be - * obtained at their site: - * http://www.national.com/pf/LM/LM77.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, - I2C_CLIENT_END }; - -/* The LM77 registers */ -#define LM77_REG_TEMP 0x00 -#define LM77_REG_CONF 0x01 -#define LM77_REG_TEMP_HYST 0x02 -#define LM77_REG_TEMP_CRIT 0x03 -#define LM77_REG_TEMP_MIN 0x04 -#define LM77_REG_TEMP_MAX 0x05 - -/* Each client has this additional data */ -struct lm77_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; - unsigned long last_updated; /* In jiffies */ - int temp_input; /* Temperatures */ - int temp_crit; - int temp_min; - int temp_max; - int temp_hyst; - u8 alarms; -}; - -static int lm77_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm77_detect(struct i2c_client *client, struct i2c_board_info *info); -static void lm77_init_client(struct i2c_client *client); -static int lm77_remove(struct i2c_client *client); -static u16 lm77_read_value(struct i2c_client *client, u8 reg); -static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value); - -static struct lm77_data *lm77_update_device(struct device *dev); - - -static const struct i2c_device_id lm77_id[] = { - { "lm77", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm77_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver lm77_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm77", - }, - .probe = lm77_probe, - .remove = lm77_remove, - .id_table = lm77_id, - .detect = lm77_detect, - .address_list = normal_i2c, -}; - -/* straight from the datasheet */ -#define LM77_TEMP_MIN (-55000) -#define LM77_TEMP_MAX 125000 - -/* - * In the temperature registers, the low 3 bits are not part of the - * temperature values; they are the status bits. - */ -static inline s16 LM77_TEMP_TO_REG(int temp) -{ - int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX); - return (ntemp / 500) * 8; -} - -static inline int LM77_TEMP_FROM_REG(s16 reg) -{ - return (reg / 8) * 500; -} - -/* sysfs stuff */ - -/* read routines for temperature limits */ -#define show(value) \ -static ssize_t show_##value(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - struct lm77_data *data = lm77_update_device(dev); \ - return sprintf(buf, "%d\n", data->value); \ -} - -show(temp_input); -show(temp_crit); -show(temp_min); -show(temp_max); - -/* read routines for hysteresis values */ -static ssize_t show_temp_crit_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm77_data *data = lm77_update_device(dev); - return sprintf(buf, "%d\n", data->temp_crit - data->temp_hyst); -} -static ssize_t show_temp_min_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm77_data *data = lm77_update_device(dev); - return sprintf(buf, "%d\n", data->temp_min + data->temp_hyst); -} -static ssize_t show_temp_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm77_data *data = lm77_update_device(dev); - return sprintf(buf, "%d\n", data->temp_max - data->temp_hyst); -} - -/* write routines */ -#define set(value, reg) \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm77_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ - \ - mutex_lock(&data->update_lock); \ - data->value = val; \ - lm77_write_value(client, reg, LM77_TEMP_TO_REG(data->value)); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -set(temp_min, LM77_REG_TEMP_MIN); -set(temp_max, LM77_REG_TEMP_MAX); - -/* - * hysteresis is stored as a relative value on the chip, so it has to be - * converted first - */ -static ssize_t set_temp_crit_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm77_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_hyst = data->temp_crit - val; - lm77_write_value(client, LM77_REG_TEMP_HYST, - LM77_TEMP_TO_REG(data->temp_hyst)); - mutex_unlock(&data->update_lock); - return count; -} - -/* preserve hysteresis when setting T_crit */ -static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm77_data *data = i2c_get_clientdata(client); - int oldcrithyst; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - oldcrithyst = data->temp_crit - data->temp_hyst; - data->temp_crit = val; - data->temp_hyst = data->temp_crit - oldcrithyst; - lm77_write_value(client, LM77_REG_TEMP_CRIT, - LM77_TEMP_TO_REG(data->temp_crit)); - lm77_write_value(client, LM77_REG_TEMP_HYST, - LM77_TEMP_TO_REG(data->temp_hyst)); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct lm77_data *data = lm77_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, - show_temp_input, NULL); -static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, - show_temp_crit, set_temp_crit); -static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - show_temp_min, set_temp_min); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp_max, set_temp_max); - -static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, - show_temp_crit_hyst, set_temp_crit_hyst); -static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, - show_temp_min_hyst, NULL); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, - show_temp_max_hyst, NULL); - -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); - -static struct attribute *lm77_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_crit.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_crit_hyst.attr, - &dev_attr_temp1_min_hyst.attr, - &dev_attr_temp1_max_hyst.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm77_group = { - .attrs = lm77_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm77_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - int i, cur, conf, hyst, crit, min, max; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - /* - * Here comes the remaining detection. Since the LM77 has no - * register dedicated to identification, we have to rely on the - * following tricks: - * - * 1. the high 4 bits represent the sign and thus they should - * always be the same - * 2. the high 3 bits are unused in the configuration register - * 3. addresses 0x06 and 0x07 return the last read value - * 4. registers cycling over 8-address boundaries - * - * Word-sized registers are high-byte first. - */ - - /* addresses cycling */ - cur = i2c_smbus_read_word_data(new_client, 0); - conf = i2c_smbus_read_byte_data(new_client, 1); - hyst = i2c_smbus_read_word_data(new_client, 2); - crit = i2c_smbus_read_word_data(new_client, 3); - min = i2c_smbus_read_word_data(new_client, 4); - max = i2c_smbus_read_word_data(new_client, 5); - for (i = 8; i <= 0xff; i += 8) { - if (i2c_smbus_read_byte_data(new_client, i + 1) != conf - || i2c_smbus_read_word_data(new_client, i + 2) != hyst - || i2c_smbus_read_word_data(new_client, i + 3) != crit - || i2c_smbus_read_word_data(new_client, i + 4) != min - || i2c_smbus_read_word_data(new_client, i + 5) != max) - return -ENODEV; - } - - /* sign bits */ - if (((cur & 0x00f0) != 0xf0 && (cur & 0x00f0) != 0x0) - || ((hyst & 0x00f0) != 0xf0 && (hyst & 0x00f0) != 0x0) - || ((crit & 0x00f0) != 0xf0 && (crit & 0x00f0) != 0x0) - || ((min & 0x00f0) != 0xf0 && (min & 0x00f0) != 0x0) - || ((max & 0x00f0) != 0xf0 && (max & 0x00f0) != 0x0)) - return -ENODEV; - - /* unused bits */ - if (conf & 0xe0) - return -ENODEV; - - /* 0x06 and 0x07 return the last read value */ - cur = i2c_smbus_read_word_data(new_client, 0); - if (i2c_smbus_read_word_data(new_client, 6) != cur - || i2c_smbus_read_word_data(new_client, 7) != cur) - return -ENODEV; - hyst = i2c_smbus_read_word_data(new_client, 2); - if (i2c_smbus_read_word_data(new_client, 6) != hyst - || i2c_smbus_read_word_data(new_client, 7) != hyst) - return -ENODEV; - min = i2c_smbus_read_word_data(new_client, 4); - if (i2c_smbus_read_word_data(new_client, 6) != min - || i2c_smbus_read_word_data(new_client, 7) != min) - return -ENODEV; - - strlcpy(info->type, "lm77", I2C_NAME_SIZE); - - return 0; -} - -static int lm77_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm77_data *data; - int err; - - data = kzalloc(sizeof(struct lm77_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Initialize the LM77 chip */ - lm77_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &lm77_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &lm77_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int lm77_remove(struct i2c_client *client) -{ - struct lm77_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm77_group); - kfree(data); - return 0; -} - -/* - * All registers are word-sized, except for the configuration register. - * The LM77 uses the high-byte first convention. - */ -static u16 lm77_read_value(struct i2c_client *client, u8 reg) -{ - if (reg == LM77_REG_CONF) - return i2c_smbus_read_byte_data(client, reg); - else - return i2c_smbus_read_word_swapped(client, reg); -} - -static int lm77_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if (reg == LM77_REG_CONF) - return i2c_smbus_write_byte_data(client, reg, value); - else - return i2c_smbus_write_word_swapped(client, reg, value); -} - -static void lm77_init_client(struct i2c_client *client) -{ - /* Initialize the LM77 chip - turn off shutdown mode */ - int conf = lm77_read_value(client, LM77_REG_CONF); - if (conf & 1) - lm77_write_value(client, LM77_REG_CONF, conf & 0xfe); -} - -static struct lm77_data *lm77_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm77_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - dev_dbg(&client->dev, "Starting lm77 update\n"); - data->temp_input = - LM77_TEMP_FROM_REG(lm77_read_value(client, - LM77_REG_TEMP)); - data->temp_hyst = - LM77_TEMP_FROM_REG(lm77_read_value(client, - LM77_REG_TEMP_HYST)); - data->temp_crit = - LM77_TEMP_FROM_REG(lm77_read_value(client, - LM77_REG_TEMP_CRIT)); - data->temp_min = - LM77_TEMP_FROM_REG(lm77_read_value(client, - LM77_REG_TEMP_MIN)); - data->temp_max = - LM77_TEMP_FROM_REG(lm77_read_value(client, - LM77_REG_TEMP_MAX)); - data->alarms = - lm77_read_value(client, LM77_REG_TEMP) & 0x0007; - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(lm77_driver); - -MODULE_AUTHOR("Andras BALI "); -MODULE_DESCRIPTION("LM77 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm78.c b/ANDROID_3.4.5/drivers/hwmon/lm78.c deleted file mode 100644 index f6bc414e..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm78.c +++ /dev/null @@ -1,1126 +0,0 @@ -/* - * lm78.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998, 1999 Frodo Looijaard - * Copyright (c) 2007, 2011 Jean Delvare - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ISA -#include -#include -#include -#endif - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, I2C_CLIENT_END }; -enum chips { lm78, lm79 }; - -/* Many LM78 constants specified below */ - -/* Length of ISA address segment */ -#define LM78_EXTENT 8 - -/* Where are the ISA address/data registers relative to the base address */ -#define LM78_ADDR_REG_OFFSET 5 -#define LM78_DATA_REG_OFFSET 6 - -/* The LM78 registers */ -#define LM78_REG_IN_MAX(nr) (0x2b + (nr) * 2) -#define LM78_REG_IN_MIN(nr) (0x2c + (nr) * 2) -#define LM78_REG_IN(nr) (0x20 + (nr)) - -#define LM78_REG_FAN_MIN(nr) (0x3b + (nr)) -#define LM78_REG_FAN(nr) (0x28 + (nr)) - -#define LM78_REG_TEMP 0x27 -#define LM78_REG_TEMP_OVER 0x39 -#define LM78_REG_TEMP_HYST 0x3a - -#define LM78_REG_ALARM1 0x41 -#define LM78_REG_ALARM2 0x42 - -#define LM78_REG_VID_FANDIV 0x47 - -#define LM78_REG_CONFIG 0x40 -#define LM78_REG_CHIPID 0x49 -#define LM78_REG_I2C_ADDR 0x48 - - -/* - * Conversions. Rounding and limit checking is only done on the TO_REG - * variants. - */ - -/* - * IN: mV (0V to 4.08V) - * REG: 16mV/bit - */ -static inline u8 IN_TO_REG(unsigned long val) -{ - unsigned long nval = SENSORS_LIMIT(val, 0, 4080); - return (nval + 8) / 16; -} -#define IN_FROM_REG(val) ((val) * 16) - -static inline u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm <= 0) - return 255; - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -static inline int FAN_FROM_REG(u8 val, int div) -{ - return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div); -} - -/* - * TEMP: mC (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static inline s8 TEMP_TO_REG(int val) -{ - int nval = SENSORS_LIMIT(val, -128000, 127000) ; - return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000; -} - -static inline int TEMP_FROM_REG(s8 val) -{ - return val * 1000; -} - -#define DIV_FROM_REG(val) (1 << (val)) - -struct lm78_data { - struct i2c_client *client; - struct device *hwmon_dev; - struct mutex lock; - enum chips type; - - /* For ISA device only */ - const char *name; - int isa_addr; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[7]; /* Register value */ - u8 in_max[7]; /* Register value */ - u8 in_min[7]; /* Register value */ - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - s8 temp; /* Register value */ - s8 temp_over; /* Register value */ - s8 temp_hyst; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 vid; /* Register encoding, combined */ - u16 alarms; /* Register encoding, combined */ -}; - - -static int lm78_read_value(struct lm78_data *data, u8 reg); -static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value); -static struct lm78_data *lm78_update_device(struct device *dev); -static void lm78_init_device(struct lm78_data *data); - - -/* 7 Voltages */ -static ssize_t show_in(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in[attr->index])); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[attr->index])); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[attr->index])); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val); - lm78_write_value(data, LM78_REG_IN_MIN(nr), data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val); - lm78_write_value(data, LM78_REG_IN_MAX(nr), data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_in_offset(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); - -show_in_offset(0); -show_in_offset(1); -show_in_offset(2); -show_in_offset(3); -show_in_offset(4); -show_in_offset(5); -show_in_offset(6); - -/* Temperature */ -static ssize_t show_temp(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); -} - -static ssize_t show_temp_over(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); -} - -static ssize_t set_temp_over(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct lm78_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_over = TEMP_TO_REG(val); - lm78_write_value(data, LM78_REG_TEMP_OVER, data->temp_over); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst)); -} - -static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct lm78_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_hyst = TEMP_TO_REG(val); - lm78_write_value(data, LM78_REG_TEMP_HYST, data->temp_hyst); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); -static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp_over, set_temp_over); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - show_temp_hyst, set_temp_hyst); - -/* 3 Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = lm78_update_device(dev); - int nr = attr->index; - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = lm78_update_device(dev); - int nr = attr->index; - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct lm78_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long min; - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - - switch (val) { - case 1: - data->fan_div[nr] = 0; - break; - case 2: - data->fan_div[nr] = 1; - break; - case 4: - data->fan_div[nr] = 2; - break; - case 8: - data->fan_div[nr] = 3; - break; - default: - dev_err(dev, "fan_div value %ld not " - "supported. Choose one of 1, 2, 4 or 8!\n", val); - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - reg = lm78_read_value(data, LM78_REG_VID_FANDIV); - switch (nr) { - case 0: - reg = (reg & 0xcf) | (data->fan_div[nr] << 4); - break; - case 1: - reg = (reg & 0x3f) | (data->fan_div[nr] << 6); - break; - } - lm78_write_value(data, LM78_REG_VID_FANDIV, reg); - - data->fan_min[nr] = - FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - lm78_write_value(data, LM78_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -#define show_fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); - -show_fan_offset(1); -show_fan_offset(2); -show_fan_offset(3); - -/* Fan 3 divisor is locked in H/W */ -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - show_fan_div, set_fan_div, 1); -static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2); - -/* VID */ -static ssize_t show_vid(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, 82)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -/* Alarms */ -static ssize_t show_alarms(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct lm78_data *data = lm78_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct lm78_data *data = lm78_update_device(dev); - int nr = to_sensor_dev_attr(da)->index; - return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); - -static struct attribute *lm78_attributes[] = { - &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, - &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, - &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, - &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, - &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, - &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, - &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, - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_cpu0_vid.attr, - - NULL -}; - -static const struct attribute_group lm78_group = { - .attrs = lm78_attributes, -}; - -/* - * ISA related code - */ -#ifdef CONFIG_ISA - -/* ISA device, if found */ -static struct platform_device *pdev; - -static unsigned short isa_address = 0x290; - -/* - * I2C devices get this name attribute automatically, but for ISA devices - * we must create it by ourselves. - */ -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct lm78_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct lm78_data *lm78_data_if_isa(void) -{ - return pdev ? platform_get_drvdata(pdev) : NULL; -} - -/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */ -static int lm78_alias_detect(struct i2c_client *client, u8 chipid) -{ - struct lm78_data *isa; - int i; - - if (!pdev) /* No ISA chip */ - return 0; - isa = platform_get_drvdata(pdev); - - if (lm78_read_value(isa, LM78_REG_I2C_ADDR) != client->addr) - return 0; /* Address doesn't match */ - if ((lm78_read_value(isa, LM78_REG_CHIPID) & 0xfe) != (chipid & 0xfe)) - return 0; /* Chip type doesn't match */ - - /* - * We compare all the limit registers, the config register and the - * interrupt mask registers - */ - for (i = 0x2b; i <= 0x3d; i++) { - if (lm78_read_value(isa, i) != - i2c_smbus_read_byte_data(client, i)) - return 0; - } - if (lm78_read_value(isa, LM78_REG_CONFIG) != - i2c_smbus_read_byte_data(client, LM78_REG_CONFIG)) - return 0; - for (i = 0x43; i <= 0x46; i++) { - if (lm78_read_value(isa, i) != - i2c_smbus_read_byte_data(client, i)) - return 0; - } - - return 1; -} -#else /* !CONFIG_ISA */ - -static int lm78_alias_detect(struct i2c_client *client, u8 chipid) -{ - return 0; -} - -static struct lm78_data *lm78_data_if_isa(void) -{ - return NULL; -} -#endif /* CONFIG_ISA */ - -static int lm78_i2c_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - int i; - struct lm78_data *isa = lm78_data_if_isa(); - const char *client_name; - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* - * We block updates of the ISA device to minimize the risk of - * concurrent access to the same LM78 chip through different - * interfaces. - */ - if (isa) - mutex_lock(&isa->update_lock); - - if ((i2c_smbus_read_byte_data(client, LM78_REG_CONFIG) & 0x80) - || i2c_smbus_read_byte_data(client, LM78_REG_I2C_ADDR) != address) - goto err_nodev; - - /* Explicitly prevent the misdetection of Winbond chips */ - i = i2c_smbus_read_byte_data(client, 0x4f); - if (i == 0xa3 || i == 0x5c) - goto err_nodev; - - /* Determine the chip type. */ - i = i2c_smbus_read_byte_data(client, LM78_REG_CHIPID); - if (i == 0x00 || i == 0x20 /* LM78 */ - || i == 0x40) /* LM78-J */ - client_name = "lm78"; - else if ((i & 0xfe) == 0xc0) - client_name = "lm79"; - else - goto err_nodev; - - if (lm78_alias_detect(client, i)) { - dev_dbg(&adapter->dev, "Device at 0x%02x appears to " - "be the same as ISA device\n", address); - goto err_nodev; - } - - if (isa) - mutex_unlock(&isa->update_lock); - - strlcpy(info->type, client_name, I2C_NAME_SIZE); - - return 0; - - err_nodev: - if (isa) - mutex_unlock(&isa->update_lock); - return -ENODEV; -} - -static int lm78_i2c_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm78_data *data; - int err; - - data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->client = client; - data->type = id->driver_data; - - /* Initialize the LM78 chip */ - lm78_init_device(data); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm78_group); - if (err) - goto ERROR3; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto ERROR4; - } - - return 0; - -ERROR4: - sysfs_remove_group(&client->dev.kobj, &lm78_group); -ERROR3: - kfree(data); - return err; -} - -static int lm78_i2c_remove(struct i2c_client *client) -{ - struct lm78_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm78_group); - kfree(data); - - return 0; -} - -static const struct i2c_device_id lm78_i2c_id[] = { - { "lm78", lm78 }, - { "lm79", lm79 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm78_i2c_id); - -static struct i2c_driver lm78_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm78", - }, - .probe = lm78_i2c_probe, - .remove = lm78_i2c_remove, - .id_table = lm78_i2c_id, - .detect = lm78_i2c_detect, - .address_list = normal_i2c, -}; - -/* - * The SMBus locks itself, but ISA access must be locked explicitly! - * We don't want to lock the whole ISA bus, so we lock each client - * separately. - * We ignore the LM78 BUSY flag at this moment - it could lead to deadlocks, - * would slow down the LM78 access and should not be necessary. - */ -static int lm78_read_value(struct lm78_data *data, u8 reg) -{ - struct i2c_client *client = data->client; - -#ifdef CONFIG_ISA - if (!client) { /* ISA device */ - int res; - mutex_lock(&data->lock); - outb_p(reg, data->isa_addr + LM78_ADDR_REG_OFFSET); - res = inb_p(data->isa_addr + LM78_DATA_REG_OFFSET); - mutex_unlock(&data->lock); - return res; - } else -#endif - return i2c_smbus_read_byte_data(client, reg); -} - -static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value) -{ - struct i2c_client *client = data->client; - -#ifdef CONFIG_ISA - if (!client) { /* ISA device */ - mutex_lock(&data->lock); - outb_p(reg, data->isa_addr + LM78_ADDR_REG_OFFSET); - outb_p(value, data->isa_addr + LM78_DATA_REG_OFFSET); - mutex_unlock(&data->lock); - return 0; - } else -#endif - return i2c_smbus_write_byte_data(client, reg, value); -} - -static void lm78_init_device(struct lm78_data *data) -{ - u8 config; - int i; - - /* Start monitoring */ - config = lm78_read_value(data, LM78_REG_CONFIG); - if ((config & 0x09) != 0x01) - lm78_write_value(data, LM78_REG_CONFIG, - (config & 0xf7) | 0x01); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 3; i++) { - data->fan_min[i] = lm78_read_value(data, - LM78_REG_FAN_MIN(i)); - } - - mutex_init(&data->update_lock); -} - -static struct lm78_data *lm78_update_device(struct device *dev) -{ - struct lm78_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - - dev_dbg(dev, "Starting lm78 update\n"); - - for (i = 0; i <= 6; i++) { - data->in[i] = - lm78_read_value(data, LM78_REG_IN(i)); - data->in_min[i] = - lm78_read_value(data, LM78_REG_IN_MIN(i)); - data->in_max[i] = - lm78_read_value(data, LM78_REG_IN_MAX(i)); - } - for (i = 0; i < 3; i++) { - data->fan[i] = - lm78_read_value(data, LM78_REG_FAN(i)); - data->fan_min[i] = - lm78_read_value(data, LM78_REG_FAN_MIN(i)); - } - data->temp = lm78_read_value(data, LM78_REG_TEMP); - data->temp_over = - lm78_read_value(data, LM78_REG_TEMP_OVER); - data->temp_hyst = - lm78_read_value(data, LM78_REG_TEMP_HYST); - i = lm78_read_value(data, LM78_REG_VID_FANDIV); - data->vid = i & 0x0f; - if (data->type == lm79) - data->vid |= - (lm78_read_value(data, LM78_REG_CHIPID) & - 0x01) << 4; - else - data->vid |= 0x10; - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - data->alarms = lm78_read_value(data, LM78_REG_ALARM1) + - (lm78_read_value(data, LM78_REG_ALARM2) << 8); - data->last_updated = jiffies; - data->valid = 1; - - data->fan_div[2] = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -#ifdef CONFIG_ISA -static int __devinit lm78_isa_probe(struct platform_device *pdev) -{ - int err; - struct lm78_data *data; - struct resource *res; - - /* Reserve the ISA region */ - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) { - err = -EBUSY; - goto exit; - } - - data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release_region; - } - mutex_init(&data->lock); - data->isa_addr = res->start; - platform_set_drvdata(pdev, data); - - if (lm78_read_value(data, LM78_REG_CHIPID) & 0x80) { - data->type = lm79; - data->name = "lm79"; - } else { - data->type = lm78; - data->name = "lm78"; - } - - /* Initialize the LM78 chip */ - lm78_init_device(data); - - /* Register sysfs hooks */ - err = sysfs_create_group(&pdev->dev.kobj, &lm78_group); - if (err) - goto exit_remove_files; - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_remove_files; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - - exit_remove_files: - sysfs_remove_group(&pdev->dev.kobj, &lm78_group); - device_remove_file(&pdev->dev, &dev_attr_name); - kfree(data); - exit_release_region: - release_region(res->start + LM78_ADDR_REG_OFFSET, 2); - exit: - return err; -} - -static int __devexit lm78_isa_remove(struct platform_device *pdev) -{ - struct lm78_data *data = platform_get_drvdata(pdev); - struct resource *res; - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &lm78_group); - device_remove_file(&pdev->dev, &dev_attr_name); - kfree(data); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start + LM78_ADDR_REG_OFFSET, 2); - - return 0; -} - -static struct platform_driver lm78_isa_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "lm78", - }, - .probe = lm78_isa_probe, - .remove = __devexit_p(lm78_isa_remove), -}; - -/* return 1 if a supported chip is found, 0 otherwise */ -static int __init lm78_isa_found(unsigned short address) -{ - int val, save, found = 0; - int port; - - /* - * Some boards declare base+0 to base+7 as a PNP device, some base+4 - * to base+7 and some base+5 to base+6. So we better request each port - * individually for the probing phase. - */ - for (port = address; port < address + LM78_EXTENT; port++) { - if (!request_region(port, 1, "lm78")) { - pr_debug("Failed to request port 0x%x\n", port); - goto release; - } - } - -#define REALLY_SLOW_IO - /* - * We need the timeouts for at least some LM78-like - * chips. But only if we read 'undefined' registers. - */ - val = inb_p(address + 1); - if (inb_p(address + 2) != val - || inb_p(address + 3) != val - || inb_p(address + 7) != val) - goto release; -#undef REALLY_SLOW_IO - - /* - * We should be able to change the 7 LSB of the address port. The - * MSB (busy flag) should be clear initially, set after the write. - */ - save = inb_p(address + LM78_ADDR_REG_OFFSET); - if (save & 0x80) - goto release; - val = ~save & 0x7f; - outb_p(val, address + LM78_ADDR_REG_OFFSET); - if (inb_p(address + LM78_ADDR_REG_OFFSET) != (val | 0x80)) { - outb_p(save, address + LM78_ADDR_REG_OFFSET); - goto release; - } - - /* We found a device, now see if it could be an LM78 */ - outb_p(LM78_REG_CONFIG, address + LM78_ADDR_REG_OFFSET); - val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val & 0x80) - goto release; - outb_p(LM78_REG_I2C_ADDR, address + LM78_ADDR_REG_OFFSET); - val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val < 0x03 || val > 0x77) /* Not a valid I2C address */ - goto release; - - /* The busy flag should be clear again */ - if (inb_p(address + LM78_ADDR_REG_OFFSET) & 0x80) - goto release; - - /* Explicitly prevent the misdetection of Winbond chips */ - outb_p(0x4f, address + LM78_ADDR_REG_OFFSET); - val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val == 0xa3 || val == 0x5c) - goto release; - - /* Explicitly prevent the misdetection of ITE chips */ - outb_p(0x58, address + LM78_ADDR_REG_OFFSET); - val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val == 0x90) - goto release; - - /* Determine the chip type */ - outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET); - val = inb_p(address + LM78_DATA_REG_OFFSET); - if (val == 0x00 || val == 0x20 /* LM78 */ - || val == 0x40 /* LM78-J */ - || (val & 0xfe) == 0xc0) /* LM79 */ - found = 1; - - if (found) - pr_info("Found an %s chip at %#x\n", - val & 0x80 ? "LM79" : "LM78", (int)address); - - release: - for (port--; port >= address; port--) - release_region(port, 1); - return found; -} - -static int __init lm78_isa_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + LM78_EXTENT - 1, - .name = "lm78", - .flags = IORESOURCE_IO, - }; - int err; - - pdev = platform_device_alloc("lm78", address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - pdev = NULL; - return err; -} - -static int __init lm78_isa_register(void) -{ - int res; - - if (lm78_isa_found(isa_address)) { - res = platform_driver_register(&lm78_isa_driver); - if (res) - goto exit; - - /* Sets global pdev as a side effect */ - res = lm78_isa_device_add(isa_address); - if (res) - goto exit_unreg_isa_driver; - } - - return 0; - - exit_unreg_isa_driver: - platform_driver_unregister(&lm78_isa_driver); - exit: - return res; -} - -static void lm78_isa_unregister(void) -{ - if (pdev) { - platform_device_unregister(pdev); - platform_driver_unregister(&lm78_isa_driver); - } -} -#else /* !CONFIG_ISA */ - -static int __init lm78_isa_register(void) -{ - return 0; -} - -static void lm78_isa_unregister(void) -{ -} -#endif /* CONFIG_ISA */ - -static int __init sm_lm78_init(void) -{ - int res; - - /* - * We register the ISA device first, so that we can skip the - * registration of an I2C interface to the same device. - */ - res = lm78_isa_register(); - if (res) - goto exit; - - res = i2c_add_driver(&lm78_driver); - if (res) - goto exit_unreg_isa_device; - - return 0; - - exit_unreg_isa_device: - lm78_isa_unregister(); - exit: - return res; -} - -static void __exit sm_lm78_exit(void) -{ - lm78_isa_unregister(); - i2c_del_driver(&lm78_driver); -} - -MODULE_AUTHOR("Frodo Looijaard, Jean Delvare "); -MODULE_DESCRIPTION("LM78/LM79 driver"); -MODULE_LICENSE("GPL"); - -module_init(sm_lm78_init); -module_exit(sm_lm78_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm80.c b/ANDROID_3.4.5/drivers/hwmon/lm80.c deleted file mode 100644 index e2c43e17..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm80.c +++ /dev/null @@ -1,737 +0,0 @@ -/* - * lm80.c - From lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 1998, 1999 Frodo Looijaard - * and Philip Edelbrock - * - * Ported to Linux 2.6 by Tiago Sousa - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, I2C_CLIENT_END }; - -/* Many LM80 constants specified below */ - -/* The LM80 registers */ -#define LM80_REG_IN_MAX(nr) (0x2a + (nr) * 2) -#define LM80_REG_IN_MIN(nr) (0x2b + (nr) * 2) -#define LM80_REG_IN(nr) (0x20 + (nr)) - -#define LM80_REG_FAN1 0x28 -#define LM80_REG_FAN2 0x29 -#define LM80_REG_FAN_MIN(nr) (0x3b + (nr)) - -#define LM80_REG_TEMP 0x27 -#define LM80_REG_TEMP_HOT_MAX 0x38 -#define LM80_REG_TEMP_HOT_HYST 0x39 -#define LM80_REG_TEMP_OS_MAX 0x3a -#define LM80_REG_TEMP_OS_HYST 0x3b - -#define LM80_REG_CONFIG 0x00 -#define LM80_REG_ALARM1 0x01 -#define LM80_REG_ALARM2 0x02 -#define LM80_REG_MASK1 0x03 -#define LM80_REG_MASK2 0x04 -#define LM80_REG_FANDIV 0x05 -#define LM80_REG_RES 0x06 - -#define LM96080_REG_CONV_RATE 0x07 -#define LM96080_REG_MAN_ID 0x3e -#define LM96080_REG_DEV_ID 0x3f - - -/* - * Conversions. Rounding and limit checking is only done on the TO_REG - * variants. Note that you should be a bit careful with which arguments - * these macros are called: arguments may be evaluated more than once. - * Fixing this is just not worth it. - */ - -#define IN_TO_REG(val) (SENSORS_LIMIT(((val) + 5) / 10, 0, 255)) -#define IN_FROM_REG(val) ((val) * 10) - -static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ - (val) == 255 ? 0 : 1350000/((div) * (val))) - -static inline long TEMP_FROM_REG(u16 temp) -{ - long res; - - temp >>= 4; - if (temp < 0x0800) - res = 625 * (long) temp; - else - res = ((long) temp - 0x01000) * 625; - - return res / 10; -} - -#define TEMP_LIMIT_FROM_REG(val) (((val) > 0x80 ? \ - (val) - 0x100 : (val)) * 1000) - -#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val) < 0 ? \ - ((val) - 500) / 1000 : ((val) + 500) / 1000, 0, 255) - -#define DIV_FROM_REG(val) (1 << (val)) - -/* - * Client data (each client gets its own) - */ - -struct lm80_data { - struct device *hwmon_dev; - struct mutex update_lock; - char error; /* !=0 if error occurred during last update */ - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[7]; /* Register value */ - u8 in_max[7]; /* Register value */ - u8 in_min[7]; /* Register value */ - u8 fan[2]; /* Register value */ - u8 fan_min[2]; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ - u16 temp; /* Register values, shifted right */ - u8 temp_hot_max; /* Register value */ - u8 temp_hot_hyst; /* Register value */ - u8 temp_os_max; /* Register value */ - u8 temp_os_hyst; /* Register value */ - u16 alarms; /* Register encoding, combined */ -}; - -/* - * Functions declaration - */ - -static int lm80_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info); -static void lm80_init_client(struct i2c_client *client); -static int lm80_remove(struct i2c_client *client); -static struct lm80_data *lm80_update_device(struct device *dev); -static int lm80_read_value(struct i2c_client *client, u8 reg); -static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id lm80_id[] = { - { "lm80", 0 }, - { "lm96080", 1 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm80_id); - -static struct i2c_driver lm80_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm80", - }, - .probe = lm80_probe, - .remove = lm80_remove, - .id_table = lm80_id, - .detect = lm80_detect, - .address_list = normal_i2c, -}; - -/* - * Sysfs stuff - */ - -#define show_in(suffix, value) \ -static ssize_t show_in_##suffix(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct lm80_data *data = lm80_update_device(dev); \ - if (IS_ERR(data)) \ - return PTR_ERR(data); \ - return sprintf(buf, "%d\n", IN_FROM_REG(data->value[nr])); \ -} -show_in(min, in_min) -show_in(max, in_max) -show_in(input, in) - -#define set_in(suffix, value, reg) \ -static ssize_t set_in_##suffix(struct device *dev, \ - struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm80_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err < 0) \ - return err; \ -\ - mutex_lock(&data->update_lock);\ - data->value[nr] = IN_TO_REG(val); \ - lm80_write_value(client, reg(nr), data->value[nr]); \ - mutex_unlock(&data->update_lock);\ - return count; \ -} -set_in(min, in_min, LM80_REG_IN_MIN) -set_in(max, in_max, LM80_REG_IN_MAX) - -#define show_fan(suffix, value) \ -static ssize_t show_fan_##suffix(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct lm80_data *data = lm80_update_device(dev); \ - if (IS_ERR(data)) \ - return PTR_ERR(data); \ - return sprintf(buf, "%d\n", FAN_FROM_REG(data->value[nr], \ - DIV_FROM_REG(data->fan_div[nr]))); \ -} -show_fan(min, fan_min) -show_fan(input, fan) - -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm80_data *data = lm80_update_device(dev); - if (IS_ERR(data)) - return PTR_ERR(data); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm80_data *data = i2c_get_clientdata(client); - unsigned long val; - int err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm80_data *data = i2c_get_clientdata(client); - unsigned long min, val; - u8 reg; - int err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - /* Save fan_min */ - mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - - switch (val) { - case 1: - data->fan_div[nr] = 0; - break; - case 2: - data->fan_div[nr] = 1; - break; - case 4: - data->fan_div[nr] = 2; - break; - case 8: - data->fan_div[nr] = 3; - break; - default: - dev_err(&client->dev, "fan_div value %ld not " - "supported. Choose one of 1, 2, 4 or 8!\n", val); - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1)))) - | (data->fan_div[nr] << (2 * (nr + 1))); - lm80_write_value(client, LM80_REG_FANDIV, reg); - - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_temp_input1(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm80_data *data = lm80_update_device(dev); - if (IS_ERR(data)) - return PTR_ERR(data); - return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp)); -} - -#define show_temp(suffix, value) \ -static ssize_t show_temp_##suffix(struct device *dev, \ - struct device_attribute *attr, char *buf) \ -{ \ - struct lm80_data *data = lm80_update_device(dev); \ - if (IS_ERR(data)) \ - return PTR_ERR(data); \ - return sprintf(buf, "%d\n", TEMP_LIMIT_FROM_REG(data->value)); \ -} -show_temp(hot_max, temp_hot_max); -show_temp(hot_hyst, temp_hot_hyst); -show_temp(os_max, temp_os_max); -show_temp(os_hyst, temp_os_hyst); - -#define set_temp(suffix, value, reg) \ -static ssize_t set_temp_##suffix(struct device *dev, \ - struct device_attribute *attr, const char *buf, size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm80_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err < 0) \ - return err; \ -\ - mutex_lock(&data->update_lock); \ - data->value = TEMP_LIMIT_TO_REG(val); \ - lm80_write_value(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} -set_temp(hot_max, temp_hot_max, LM80_REG_TEMP_HOT_MAX); -set_temp(hot_hyst, temp_hot_hyst, LM80_REG_TEMP_HOT_HYST); -set_temp(os_max, temp_os_max, LM80_REG_TEMP_OS_MAX); -set_temp(os_hyst, temp_os_hyst, LM80_REG_TEMP_OS_HYST); - -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm80_data *data = lm80_update_device(dev); - if (IS_ERR(data)) - return PTR_ERR(data); - return sprintf(buf, "%u\n", data->alarms); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct lm80_data *data = lm80_update_device(dev); - if (IS_ERR(data)) - return PTR_ERR(data); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 0); -static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 3); -static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 4); -static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 5); -static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, - show_in_min, set_in_min, 6); -static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 0); -static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 1); -static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 2); -static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 3); -static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 4); -static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 5); -static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, - show_in_max, set_in_max, 6); -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6); -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, - show_fan_div, set_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, - show_fan_div, set_fan_div, 1); -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max, - set_temp_hot_max); -static DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, show_temp_hot_hyst, - set_temp_hot_hyst); -static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_os_max, - set_temp_os_max); -static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_os_hyst, - set_temp_os_hyst); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -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(fan1_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 13); - -/* - * Real code - */ - -static struct attribute *lm80_attributes[] = { - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &dev_attr_temp1_crit.attr, - &dev_attr_temp1_crit_hyst.attr, - &dev_attr_alarms.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm80_group = { - .attrs = lm80_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int i, cur, man_id, dev_id; - const char *name = NULL; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* First check for unused bits, common to both chip types */ - if ((lm80_read_value(client, LM80_REG_ALARM2) & 0xc0) - || (lm80_read_value(client, LM80_REG_CONFIG) & 0x80)) - return -ENODEV; - - /* - * The LM96080 has manufacturer and stepping/die rev registers so we - * can just check that. The LM80 does not have such registers so we - * have to use a more expensive trick. - */ - man_id = lm80_read_value(client, LM96080_REG_MAN_ID); - dev_id = lm80_read_value(client, LM96080_REG_DEV_ID); - if (man_id == 0x01 && dev_id == 0x08) { - /* Check more unused bits for confirmation */ - if (lm80_read_value(client, LM96080_REG_CONV_RATE) & 0xfe) - return -ENODEV; - - name = "lm96080"; - } else { - /* Check 6-bit addressing */ - for (i = 0x2a; i <= 0x3d; i++) { - cur = i2c_smbus_read_byte_data(client, i); - if ((i2c_smbus_read_byte_data(client, i + 0x40) != cur) - || (i2c_smbus_read_byte_data(client, i + 0x80) != cur) - || (i2c_smbus_read_byte_data(client, i + 0xc0) != cur)) - return -ENODEV; - } - - name = "lm80"; - } - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int lm80_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm80_data *data; - int err; - - data = kzalloc(sizeof(struct lm80_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the LM80 chip */ - lm80_init_client(client); - - /* A few vars need to be filled upon startup */ - data->fan_min[0] = lm80_read_value(client, LM80_REG_FAN_MIN(1)); - data->fan_min[1] = lm80_read_value(client, LM80_REG_FAN_MIN(2)); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm80_group); - if (err) - goto error_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_remove; - } - - return 0; - -error_remove: - sysfs_remove_group(&client->dev.kobj, &lm80_group); -error_free: - kfree(data); -exit: - return err; -} - -static int lm80_remove(struct i2c_client *client) -{ - struct lm80_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm80_group); - - kfree(data); - return 0; -} - -static int lm80_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -/* Called when we have found a new LM80. */ -static void lm80_init_client(struct i2c_client *client) -{ - /* - * Reset all except Watchdog values and last conversion values - * This sets fan-divs to 2, among others. This makes most other - * initializations unnecessary - */ - lm80_write_value(client, LM80_REG_CONFIG, 0x80); - /* Set 11-bit temperature resolution */ - lm80_write_value(client, LM80_REG_RES, 0x08); - - /* Start monitoring */ - lm80_write_value(client, LM80_REG_CONFIG, 0x01); -} - -static struct lm80_data *lm80_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm80_data *data = i2c_get_clientdata(client); - int i; - int rv; - int prev_rv; - struct lm80_data *ret = data; - - mutex_lock(&data->update_lock); - - if (data->error) - lm80_init_client(client); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - dev_dbg(&client->dev, "Starting lm80 update\n"); - for (i = 0; i <= 6; i++) { - rv = lm80_read_value(client, LM80_REG_IN(i)); - if (rv < 0) - goto abort; - data->in[i] = rv; - - rv = lm80_read_value(client, LM80_REG_IN_MIN(i)); - if (rv < 0) - goto abort; - data->in_min[i] = rv; - - rv = lm80_read_value(client, LM80_REG_IN_MAX(i)); - if (rv < 0) - goto abort; - data->in_max[i] = rv; - } - - rv = lm80_read_value(client, LM80_REG_FAN1); - if (rv < 0) - goto abort; - data->fan[0] = rv; - - rv = lm80_read_value(client, LM80_REG_FAN_MIN(1)); - if (rv < 0) - goto abort; - data->fan_min[0] = rv; - - rv = lm80_read_value(client, LM80_REG_FAN2); - if (rv < 0) - goto abort; - data->fan[1] = rv; - - rv = lm80_read_value(client, LM80_REG_FAN_MIN(2)); - if (rv < 0) - goto abort; - data->fan_min[1] = rv; - - prev_rv = rv = lm80_read_value(client, LM80_REG_TEMP); - if (rv < 0) - goto abort; - rv = lm80_read_value(client, LM80_REG_RES); - if (rv < 0) - goto abort; - data->temp = (prev_rv << 8) | (rv & 0xf0); - - rv = lm80_read_value(client, LM80_REG_TEMP_OS_MAX); - if (rv < 0) - goto abort; - data->temp_os_max = rv; - - rv = lm80_read_value(client, LM80_REG_TEMP_OS_HYST); - if (rv < 0) - goto abort; - data->temp_os_hyst = rv; - - rv = lm80_read_value(client, LM80_REG_TEMP_HOT_MAX); - if (rv < 0) - goto abort; - data->temp_hot_max = rv; - - rv = lm80_read_value(client, LM80_REG_TEMP_HOT_HYST); - if (rv < 0) - goto abort; - data->temp_hot_hyst = rv; - - rv = lm80_read_value(client, LM80_REG_FANDIV); - if (rv < 0) - goto abort; - data->fan_div[0] = (rv >> 2) & 0x03; - data->fan_div[1] = (rv >> 4) & 0x03; - - prev_rv = rv = lm80_read_value(client, LM80_REG_ALARM1); - if (rv < 0) - goto abort; - rv = lm80_read_value(client, LM80_REG_ALARM2); - if (rv < 0) - goto abort; - data->alarms = prev_rv + (rv << 8); - - data->last_updated = jiffies; - data->valid = 1; - data->error = 0; - } - goto done; - -abort: - ret = ERR_PTR(rv); - data->valid = 0; - data->error = 1; - -done: - mutex_unlock(&data->update_lock); - - return ret; -} - -module_i2c_driver(lm80_driver); - -MODULE_AUTHOR("Frodo Looijaard and " - "Philip Edelbrock "); -MODULE_DESCRIPTION("LM80 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm83.c b/ANDROID_3.4.5/drivers/hwmon/lm83.c deleted file mode 100644 index cd45b9d8..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm83.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * lm83.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2003-2009 Jean Delvare - * - * Heavily inspired from the lm78, lm75 and adm1021 drivers. The LM83 is - * a sensor chip made by National Semiconductor. It reports up to four - * temperatures (its own plus up to three external ones) with a 1 deg - * resolution and a 3-4 deg accuracy. Complete datasheet can be obtained - * from National's website at: - * http://www.national.com/pf/LM/LM83.html - * Since the datasheet omits to give the chip stepping code, I give it - * here: 0x03 (at register 0xff). - * - * Also supports the LM82 temp sensor, which is basically a stripped down - * model of the LM83. Datasheet is here: - * http://www.national.com/pf/LM/LM82.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - * Address is selected using 2 three-level pins, resulting in 9 possible - * addresses. - */ - -static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; - -enum chips { lm83, lm82 }; - -/* - * The LM83 registers - * Manufacturer ID is 0x01 for National Semiconductor. - */ - -#define LM83_REG_R_MAN_ID 0xFE -#define LM83_REG_R_CHIP_ID 0xFF -#define LM83_REG_R_CONFIG 0x03 -#define LM83_REG_W_CONFIG 0x09 -#define LM83_REG_R_STATUS1 0x02 -#define LM83_REG_R_STATUS2 0x35 -#define LM83_REG_R_LOCAL_TEMP 0x00 -#define LM83_REG_R_LOCAL_HIGH 0x05 -#define LM83_REG_W_LOCAL_HIGH 0x0B -#define LM83_REG_R_REMOTE1_TEMP 0x30 -#define LM83_REG_R_REMOTE1_HIGH 0x38 -#define LM83_REG_W_REMOTE1_HIGH 0x50 -#define LM83_REG_R_REMOTE2_TEMP 0x01 -#define LM83_REG_R_REMOTE2_HIGH 0x07 -#define LM83_REG_W_REMOTE2_HIGH 0x0D -#define LM83_REG_R_REMOTE3_TEMP 0x31 -#define LM83_REG_R_REMOTE3_HIGH 0x3A -#define LM83_REG_W_REMOTE3_HIGH 0x52 -#define LM83_REG_R_TCRIT 0x42 -#define LM83_REG_W_TCRIT 0x5A - -/* - * Conversions and various macros - * The LM83 uses signed 8-bit values with LSB = 1 degree Celsius. - */ - -#define TEMP_FROM_REG(val) ((val) * 1000) -#define TEMP_TO_REG(val) ((val) <= -128000 ? -128 : \ - (val) >= 127000 ? 127 : \ - (val) < 0 ? ((val) - 500) / 1000 : \ - ((val) + 500) / 1000) - -static const u8 LM83_REG_R_TEMP[] = { - LM83_REG_R_LOCAL_TEMP, - LM83_REG_R_REMOTE1_TEMP, - LM83_REG_R_REMOTE2_TEMP, - LM83_REG_R_REMOTE3_TEMP, - LM83_REG_R_LOCAL_HIGH, - LM83_REG_R_REMOTE1_HIGH, - LM83_REG_R_REMOTE2_HIGH, - LM83_REG_R_REMOTE3_HIGH, - LM83_REG_R_TCRIT, -}; - -static const u8 LM83_REG_W_HIGH[] = { - LM83_REG_W_LOCAL_HIGH, - LM83_REG_W_REMOTE1_HIGH, - LM83_REG_W_REMOTE2_HIGH, - LM83_REG_W_REMOTE3_HIGH, - LM83_REG_W_TCRIT, -}; - -/* - * Functions declaration - */ - -static int lm83_detect(struct i2c_client *new_client, - struct i2c_board_info *info); -static int lm83_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm83_remove(struct i2c_client *client); -static struct lm83_data *lm83_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id lm83_id[] = { - { "lm83", lm83 }, - { "lm82", lm82 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm83_id); - -static struct i2c_driver lm83_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm83", - }, - .probe = lm83_probe, - .remove = lm83_remove, - .id_table = lm83_id, - .detect = lm83_detect, - .address_list = normal_i2c, -}; - -/* - * Client data (each client gets its own) - */ - -struct lm83_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - s8 temp[9]; /* 0..3: input 1-4, - 4..7: high limit 1-4, - 8 : critical limit */ - u16 alarms; /* bitvector, combined */ -}; - -/* - * Sysfs stuff - */ - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm83_data *data = lm83_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct lm83_data *data = i2c_get_clientdata(client); - long val; - int nr = attr->index; - int err; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - mutex_lock(&data->update_lock); - data->temp[nr] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, LM83_REG_W_HIGH[nr - 4], - data->temp[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, - char *buf) -{ - struct lm83_data *data = lm83_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm83_data *data = lm83_update_device(dev); - int bitnr = attr->index; - - return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 4); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 5); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 6); -static SENSOR_DEVICE_ATTR(temp4_max, S_IWUSR | S_IRUGO, show_temp, - set_temp, 7); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp, NULL, 8); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp, - set_temp, 8); -static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8); - -/* Individual alarm files */ -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15); -/* Raw alarm file for compatibility */ -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static struct attribute *lm83_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - NULL -}; - -static const struct attribute_group lm83_group = { - .attrs = lm83_attributes, -}; - -static struct attribute *lm83_attributes_opt[] = { - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp4_crit.dev_attr.attr, - - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_fault.dev_attr.attr, - &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm83_group_opt = { - .attrs = lm83_attributes_opt, -}; - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm83_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - const char *name; - u8 man_id, chip_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Detection */ - if ((i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS1) & 0xA8) || - (i2c_smbus_read_byte_data(new_client, LM83_REG_R_STATUS2) & 0x48) || - (i2c_smbus_read_byte_data(new_client, LM83_REG_R_CONFIG) & 0x41)) { - dev_dbg(&adapter->dev, "LM83 detection failed at 0x%02x\n", - new_client->addr); - return -ENODEV; - } - - /* Identification */ - man_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_MAN_ID); - if (man_id != 0x01) /* National Semiconductor */ - return -ENODEV; - - chip_id = i2c_smbus_read_byte_data(new_client, LM83_REG_R_CHIP_ID); - switch (chip_id) { - case 0x03: - name = "lm83"; - break; - case 0x01: - name = "lm82"; - break; - default: - /* identification failed */ - dev_info(&adapter->dev, - "Unsupported chip (man_id=0x%02X, chip_id=0x%02X)\n", - man_id, chip_id); - return -ENODEV; - } - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static int lm83_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm83_data *data; - int err; - - data = kzalloc(sizeof(struct lm83_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* - * Register sysfs hooks - * The LM82 can only monitor one external diode which is - * at the same register as the LM83 temp3 entry - so we - * declare 1 and 3 common, and then 2 and 4 only for the LM83. - */ - - err = sysfs_create_group(&new_client->dev.kobj, &lm83_group); - if (err) - goto exit_free; - - if (id->driver_data == lm83) { - err = sysfs_create_group(&new_client->dev.kobj, - &lm83_group_opt); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &lm83_group); - sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt); -exit_free: - kfree(data); -exit: - return err; -} - -static int lm83_remove(struct i2c_client *client) -{ - struct lm83_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm83_group); - sysfs_remove_group(&client->dev.kobj, &lm83_group_opt); - - kfree(data); - return 0; -} - -static struct lm83_data *lm83_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm83_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - int nr; - - dev_dbg(&client->dev, "Updating lm83 data.\n"); - for (nr = 0; nr < 9; nr++) { - data->temp[nr] = - i2c_smbus_read_byte_data(client, - LM83_REG_R_TEMP[nr]); - } - data->alarms = - i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1) - + (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2) - << 8); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(lm83_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("LM83 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm85.c b/ANDROID_3.4.5/drivers/hwmon/lm85.c deleted file mode 100644 index 864c7d99..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm85.c +++ /dev/null @@ -1,1720 +0,0 @@ -/* - * lm85.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998, 1999 Frodo Looijaard - * Copyright (c) 2002, 2003 Philip Pokorny - * Copyright (c) 2003 Margit Schubert-While - * Copyright (c) 2004 Justin Thiessen - * Copyright (C) 2007--2009 Jean Delvare - * - * Chip details at - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -enum chips { - any_chip, lm85b, lm85c, - adm1027, adt7463, adt7468, - emc6d100, emc6d102, emc6d103, emc6d103s -}; - -/* The LM85 registers */ - -#define LM85_REG_IN(nr) (0x20 + (nr)) -#define LM85_REG_IN_MIN(nr) (0x44 + (nr) * 2) -#define LM85_REG_IN_MAX(nr) (0x45 + (nr) * 2) - -#define LM85_REG_TEMP(nr) (0x25 + (nr)) -#define LM85_REG_TEMP_MIN(nr) (0x4e + (nr) * 2) -#define LM85_REG_TEMP_MAX(nr) (0x4f + (nr) * 2) - -/* Fan speeds are LSB, MSB (2 bytes) */ -#define LM85_REG_FAN(nr) (0x28 + (nr) * 2) -#define LM85_REG_FAN_MIN(nr) (0x54 + (nr) * 2) - -#define LM85_REG_PWM(nr) (0x30 + (nr)) - -#define LM85_REG_COMPANY 0x3e -#define LM85_REG_VERSTEP 0x3f - -#define ADT7468_REG_CFG5 0x7c -#define ADT7468_OFF64 (1 << 0) -#define ADT7468_HFPWM (1 << 1) -#define IS_ADT7468_OFF64(data) \ - ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_OFF64)) -#define IS_ADT7468_HFPWM(data) \ - ((data)->type == adt7468 && !((data)->cfg5 & ADT7468_HFPWM)) - -/* These are the recognized values for the above regs */ -#define LM85_COMPANY_NATIONAL 0x01 -#define LM85_COMPANY_ANALOG_DEV 0x41 -#define LM85_COMPANY_SMSC 0x5c -#define LM85_VERSTEP_VMASK 0xf0 -#define LM85_VERSTEP_GENERIC 0x60 -#define LM85_VERSTEP_GENERIC2 0x70 -#define LM85_VERSTEP_LM85C 0x60 -#define LM85_VERSTEP_LM85B 0x62 -#define LM85_VERSTEP_LM96000_1 0x68 -#define LM85_VERSTEP_LM96000_2 0x69 -#define LM85_VERSTEP_ADM1027 0x60 -#define LM85_VERSTEP_ADT7463 0x62 -#define LM85_VERSTEP_ADT7463C 0x6A -#define LM85_VERSTEP_ADT7468_1 0x71 -#define LM85_VERSTEP_ADT7468_2 0x72 -#define LM85_VERSTEP_EMC6D100_A0 0x60 -#define LM85_VERSTEP_EMC6D100_A1 0x61 -#define LM85_VERSTEP_EMC6D102 0x65 -#define LM85_VERSTEP_EMC6D103_A0 0x68 -#define LM85_VERSTEP_EMC6D103_A1 0x69 -#define LM85_VERSTEP_EMC6D103S 0x6A /* Also known as EMC6D103:A2 */ - -#define LM85_REG_CONFIG 0x40 - -#define LM85_REG_ALARM1 0x41 -#define LM85_REG_ALARM2 0x42 - -#define LM85_REG_VID 0x43 - -/* Automated FAN control */ -#define LM85_REG_AFAN_CONFIG(nr) (0x5c + (nr)) -#define LM85_REG_AFAN_RANGE(nr) (0x5f + (nr)) -#define LM85_REG_AFAN_SPIKE1 0x62 -#define LM85_REG_AFAN_MINPWM(nr) (0x64 + (nr)) -#define LM85_REG_AFAN_LIMIT(nr) (0x67 + (nr)) -#define LM85_REG_AFAN_CRITICAL(nr) (0x6a + (nr)) -#define LM85_REG_AFAN_HYST1 0x6d -#define LM85_REG_AFAN_HYST2 0x6e - -#define ADM1027_REG_EXTEND_ADC1 0x76 -#define ADM1027_REG_EXTEND_ADC2 0x77 - -#define EMC6D100_REG_ALARM3 0x7d -/* IN5, IN6 and IN7 */ -#define EMC6D100_REG_IN(nr) (0x70 + ((nr) - 5)) -#define EMC6D100_REG_IN_MIN(nr) (0x73 + ((nr) - 5) * 2) -#define EMC6D100_REG_IN_MAX(nr) (0x74 + ((nr) - 5) * 2) -#define EMC6D102_REG_EXTEND_ADC1 0x85 -#define EMC6D102_REG_EXTEND_ADC2 0x86 -#define EMC6D102_REG_EXTEND_ADC3 0x87 -#define EMC6D102_REG_EXTEND_ADC4 0x88 - - -/* - * Conversions. Rounding and limit checking is only done on the TO_REG - * variants. Note that you should be a bit careful with which arguments - * these macros are called: arguments may be evaluated more than once. - */ - -/* IN are scaled according to built-in resistors */ -static const int lm85_scaling[] = { /* .001 Volts */ - 2500, 2250, 3300, 5000, 12000, - 3300, 1500, 1800 /*EMC6D100*/ -}; -#define SCALE(val, from, to) (((val) * (to) + ((from) / 2)) / (from)) - -#define INS_TO_REG(n, val) \ - SENSORS_LIMIT(SCALE(val, lm85_scaling[n], 192), 0, 255) - -#define INSEXT_FROM_REG(n, val, ext) \ - SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n]) - -#define INS_FROM_REG(n, val) SCALE((val), 192, lm85_scaling[n]) - -/* FAN speed is measured using 90kHz clock */ -static inline u16 FAN_TO_REG(unsigned long val) -{ - if (!val) - return 0xffff; - return SENSORS_LIMIT(5400000 / val, 1, 0xfffe); -} -#define FAN_FROM_REG(val) ((val) == 0 ? -1 : (val) == 0xffff ? 0 : \ - 5400000 / (val)) - -/* Temperature is reported in .001 degC increments */ -#define TEMP_TO_REG(val) \ - SENSORS_LIMIT(SCALE(val, 1000, 1), -127, 127) -#define TEMPEXT_FROM_REG(val, ext) \ - SCALE(((val) << 4) + (ext), 16, 1000) -#define TEMP_FROM_REG(val) ((val) * 1000) - -#define PWM_TO_REG(val) SENSORS_LIMIT(val, 0, 255) -#define PWM_FROM_REG(val) (val) - - -/* - * ZONEs have the following parameters: - * Limit (low) temp, 1. degC - * Hysteresis (below limit), 1. degC (0-15) - * Range of speed control, .1 degC (2-80) - * Critical (high) temp, 1. degC - * - * FAN PWMs have the following parameters: - * Reference Zone, 1, 2, 3, etc. - * Spinup time, .05 sec - * PWM value at limit/low temp, 1 count - * PWM Frequency, 1. Hz - * PWM is Min or OFF below limit, flag - * Invert PWM output, flag - * - * Some chips filter the temp, others the fan. - * Filter constant (or disabled) .1 seconds - */ - -/* These are the zone temperature range encodings in .001 degree C */ -static const int lm85_range_map[] = { - 2000, 2500, 3300, 4000, 5000, 6600, 8000, 10000, - 13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000 -}; - -static int RANGE_TO_REG(int range) -{ - int i; - - /* Find the closest match */ - for (i = 0; i < 15; ++i) { - if (range <= (lm85_range_map[i] + lm85_range_map[i + 1]) / 2) - break; - } - - return i; -} -#define RANGE_FROM_REG(val) lm85_range_map[(val) & 0x0f] - -/* These are the PWM frequency encodings */ -static const int lm85_freq_map[8] = { /* 1 Hz */ - 10, 15, 23, 30, 38, 47, 61, 94 -}; -static const int adm1027_freq_map[8] = { /* 1 Hz */ - 11, 15, 22, 29, 35, 44, 59, 88 -}; - -static int FREQ_TO_REG(const int *map, int freq) -{ - int i; - - /* Find the closest match */ - for (i = 0; i < 7; ++i) - if (freq <= (map[i] + map[i + 1]) / 2) - break; - return i; -} - -static int FREQ_FROM_REG(const int *map, u8 reg) -{ - return map[reg & 0x07]; -} - -/* - * Since we can't use strings, I'm abusing these numbers - * to stand in for the following meanings: - * 1 -- PWM responds to Zone 1 - * 2 -- PWM responds to Zone 2 - * 3 -- PWM responds to Zone 3 - * 23 -- PWM responds to the higher temp of Zone 2 or 3 - * 123 -- PWM responds to highest of Zone 1, 2, or 3 - * 0 -- PWM is always at 0% (ie, off) - * -1 -- PWM is always at 100% - * -2 -- PWM responds to manual control - */ - -static const int lm85_zone_map[] = { 1, 2, 3, -1, 0, 23, 123, -2 }; -#define ZONE_FROM_REG(val) lm85_zone_map[(val) >> 5] - -static int ZONE_TO_REG(int zone) -{ - int i; - - for (i = 0; i <= 7; ++i) - if (zone == lm85_zone_map[i]) - break; - if (i > 7) /* Not found. */ - i = 3; /* Always 100% */ - return i << 5; -} - -#define HYST_TO_REG(val) SENSORS_LIMIT(((val) + 500) / 1000, 0, 15) -#define HYST_FROM_REG(val) ((val) * 1000) - -/* - * Chip sampling rates - * - * Some sensors are not updated more frequently than once per second - * so it doesn't make sense to read them more often than that. - * We cache the results and return the saved data if the driver - * is called again before a second has elapsed. - * - * Also, there is significant configuration data for this chip - * given the automatic PWM fan control that is possible. There - * are about 47 bytes of config data to only 22 bytes of actual - * readings. So, we keep the config data up to date in the cache - * when it is written and only sample it once every 1 *minute* - */ -#define LM85_DATA_INTERVAL (HZ + HZ / 2) -#define LM85_CONFIG_INTERVAL (1 * 60 * HZ) - -/* - * LM85 can automatically adjust fan speeds based on temperature - * This structure encapsulates an entire Zone config. There are - * three zones (one for each temperature input) on the lm85 - */ -struct lm85_zone { - s8 limit; /* Low temp limit */ - u8 hyst; /* Low limit hysteresis. (0-15) */ - u8 range; /* Temp range, encoded */ - s8 critical; /* "All fans ON" temp limit */ - u8 max_desired; /* - * Actual "max" temperature specified. Preserved - * to prevent "drift" as other autofan control - * values change. - */ -}; - -struct lm85_autofan { - u8 config; /* Register value */ - u8 min_pwm; /* Minimum PWM value, encoded */ - u8 min_off; /* Min PWM or OFF below "limit", flag */ -}; - -/* - * For each registered chip, we need to keep some data in memory. - * The structure is dynamically allocated. - */ -struct lm85_data { - struct device *hwmon_dev; - const int *freq_map; - enum chips type; - - bool has_vid5; /* true if VID5 is configured for ADT7463 or ADT7468 */ - - struct mutex update_lock; - int valid; /* !=0 if following fields are valid */ - unsigned long last_reading; /* In jiffies */ - unsigned long last_config; /* In jiffies */ - - u8 in[8]; /* Register value */ - u8 in_max[8]; /* Register value */ - u8 in_min[8]; /* Register value */ - s8 temp[3]; /* Register value */ - s8 temp_min[3]; /* Register value */ - s8 temp_max[3]; /* Register value */ - u16 fan[4]; /* Register value */ - u16 fan_min[4]; /* Register value */ - u8 pwm[3]; /* Register value */ - u8 pwm_freq[3]; /* Register encoding */ - u8 temp_ext[3]; /* Decoded values */ - u8 in_ext[8]; /* Decoded values */ - u8 vid; /* Register value */ - u8 vrm; /* VRM version */ - u32 alarms; /* Register encoding, combined */ - u8 cfg5; /* Config Register 5 on ADT7468 */ - struct lm85_autofan autofan[3]; - struct lm85_zone zone[3]; -}; - -static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info); -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm85_remove(struct i2c_client *client); - -static int lm85_read_value(struct i2c_client *client, u8 reg); -static void lm85_write_value(struct i2c_client *client, u8 reg, int value); -static struct lm85_data *lm85_update_device(struct device *dev); - - -static const struct i2c_device_id lm85_id[] = { - { "adm1027", adm1027 }, - { "adt7463", adt7463 }, - { "adt7468", adt7468 }, - { "lm85", any_chip }, - { "lm85b", lm85b }, - { "lm85c", lm85c }, - { "emc6d100", emc6d100 }, - { "emc6d101", emc6d100 }, - { "emc6d102", emc6d102 }, - { "emc6d103", emc6d103 }, - { "emc6d103s", emc6d103s }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm85_id); - -static struct i2c_driver lm85_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm85", - }, - .probe = lm85_probe, - .remove = lm85_remove, - .id_table = lm85_id, - .detect = lm85_detect, - .address_list = normal_i2c, -}; - - -/* 4 Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr])); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr])); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val); - lm85_write_value(client, LM85_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1) - -show_fan_offset(1); -show_fan_offset(2); -show_fan_offset(3); -show_fan_offset(4); - -/* vid, vrm, alarms */ - -static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm85_data *data = lm85_update_device(dev); - int vid; - - if (data->has_vid5) { - /* 6-pin VID (VRM 10) */ - vid = vid_from_reg(data->vid & 0x3f, data->vrm); - } else { - /* 5-pin VID (VRM 9) */ - vid = vid_from_reg(data->vid & 0x1f, data->vrm); - } - - return sprintf(buf, "%d\n", vid); -} - -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); - -static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm85_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%ld\n", (long) data->vrm); -} - -static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct lm85_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} - -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); - -static ssize_t show_alarms_reg(struct device *dev, struct device_attribute - *attr, char *buf) -{ - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); -} - -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 18); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 16); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 17); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_alarm, NULL, 14); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 13); - -/* pwm */ - -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[nr])); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm[nr] = PWM_TO_REG(val); - lm85_write_value(client, LM85_REG_PWM(nr), data->pwm[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_enable(struct device *dev, struct device_attribute - *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - int pwm_zone, enable; - - pwm_zone = ZONE_FROM_REG(data->autofan[nr].config); - switch (pwm_zone) { - case -1: /* PWM is always at 100% */ - enable = 0; - break; - case 0: /* PWM is always at 0% */ - case -2: /* PWM responds to manual control */ - enable = 1; - break; - default: /* PWM in automatic mode */ - enable = 2; - } - return sprintf(buf, "%d\n", enable); -} - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - u8 config; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - switch (val) { - case 0: - config = 3; - break; - case 1: - config = 7; - break; - case 2: - /* - * Here we have to choose arbitrarily one of the 5 possible - * configurations; I go for the safest - */ - config = 6; - break; - default: - return -EINVAL; - } - - mutex_lock(&data->update_lock); - data->autofan[nr].config = lm85_read_value(client, - LM85_REG_AFAN_CONFIG(nr)); - data->autofan[nr].config = (data->autofan[nr].config & ~0xe0) - | (config << 5); - lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), - data->autofan[nr].config); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_freq(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - int freq; - - if (IS_ADT7468_HFPWM(data)) - freq = 22500; - else - freq = FREQ_FROM_REG(data->freq_map, data->pwm_freq[nr]); - - return sprintf(buf, "%d\n", freq); -} - -static ssize_t set_pwm_freq(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - /* - * The ADT7468 has a special high-frequency PWM output mode, - * where all PWM outputs are driven by a 22.5 kHz clock. - * This might confuse the user, but there's not much we can do. - */ - if (data->type == adt7468 && val >= 11300) { /* High freq. mode */ - data->cfg5 &= ~ADT7468_HFPWM; - lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); - } else { /* Low freq. mode */ - data->pwm_freq[nr] = FREQ_TO_REG(data->freq_map, val); - lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), - (data->zone[nr].range << 4) - | data->pwm_freq[nr]); - if (data->type == adt7468) { - data->cfg5 |= ADT7468_HFPWM; - lm85_write_value(client, ADT7468_REG_CFG5, data->cfg5); - } - } - mutex_unlock(&data->update_lock); - return count; -} - -#define show_pwm_reg(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ - show_pwm_enable, set_pwm_enable, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \ - show_pwm_freq, set_pwm_freq, offset - 1) - -show_pwm_reg(1); -show_pwm_reg(2); -show_pwm_reg(3); - -/* Voltages */ - -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", INSEXT_FROM_REG(nr, data->in[nr], - data->in_ext[nr])); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_min[nr])); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = INS_TO_REG(nr, val); - lm85_write_value(client, LM85_REG_IN_MIN(nr), data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", INS_FROM_REG(nr, data->in_max[nr])); -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = INS_TO_REG(nr, val); - lm85_write_value(client, LM85_REG_IN_MAX(nr), data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_in_reg(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset) - -show_in_reg(0); -show_in_reg(1); -show_in_reg(2); -show_in_reg(3); -show_in_reg(4); -show_in_reg(5); -show_in_reg(6); -show_in_reg(7); - -/* Temps */ - -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMPEXT_FROM_REG(data->temp[nr], - data->temp_ext[nr])); -} - -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); -} - -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - if (IS_ADT7468_OFF64(data)) - val += 64; - - mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_TEMP_MIN(nr), data->temp_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - if (IS_ADT7468_OFF64(data)) - val += 64; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_TEMP_MAX(nr), data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_temp_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); - -show_temp_reg(1); -show_temp_reg(2); -show_temp_reg(3); - - -/* Automatic PWM control */ - -static ssize_t show_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", ZONE_FROM_REG(data->autofan[nr].config)); -} - -static ssize_t set_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->autofan[nr].config = (data->autofan[nr].config & (~0xe0)) - | ZONE_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr), - data->autofan[nr].config); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_auto_pwm_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", PWM_FROM_REG(data->autofan[nr].min_pwm)); -} - -static ssize_t set_pwm_auto_pwm_min(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->autofan[nr].min_pwm = PWM_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_MINPWM(nr), - data->autofan[nr].min_pwm); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm_auto_pwm_minctl(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", data->autofan[nr].min_off); -} - -static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - u8 tmp; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->autofan[nr].min_off = val; - tmp = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); - tmp &= ~(0x20 << nr); - if (data->autofan[nr].min_off) - tmp |= 0x20 << nr; - lm85_write_value(client, LM85_REG_AFAN_SPIKE1, tmp); - mutex_unlock(&data->update_lock); - return count; -} - -#define pwm_auto(offset) \ -static SENSOR_DEVICE_ATTR(pwm##offset##_auto_channels, \ - S_IRUGO | S_IWUSR, show_pwm_auto_channels, \ - set_pwm_auto_channels, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_min, \ - S_IRUGO | S_IWUSR, show_pwm_auto_pwm_min, \ - set_pwm_auto_pwm_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_auto_pwm_minctl, \ - S_IRUGO | S_IWUSR, show_pwm_auto_pwm_minctl, \ - set_pwm_auto_pwm_minctl, offset - 1) - -pwm_auto(1); -pwm_auto(2); -pwm_auto(3); - -/* Temperature settings for automatic PWM control */ - -static ssize_t show_temp_auto_temp_off(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->zone[nr].limit) - - HYST_FROM_REG(data->zone[nr].hyst)); -} - -static ssize_t set_temp_auto_temp_off(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - int min; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - min = TEMP_FROM_REG(data->zone[nr].limit); - data->zone[nr].hyst = HYST_TO_REG(min - val); - if (nr == 0 || nr == 1) { - lm85_write_value(client, LM85_REG_AFAN_HYST1, - (data->zone[0].hyst << 4) - | data->zone[1].hyst); - } else { - lm85_write_value(client, LM85_REG_AFAN_HYST2, - (data->zone[2].hyst << 4)); - } - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_auto_temp_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->zone[nr].limit)); -} - -static ssize_t set_temp_auto_temp_min(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->zone[nr].limit = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_LIMIT(nr), - data->zone[nr].limit); - -/* Update temp_auto_max and temp_auto_range */ - data->zone[nr].range = RANGE_TO_REG( - TEMP_FROM_REG(data->zone[nr].max_desired) - - TEMP_FROM_REG(data->zone[nr].limit)); - lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), - ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_auto_temp_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->zone[nr].limit) + - RANGE_FROM_REG(data->zone[nr].range)); -} - -static ssize_t set_temp_auto_temp_max(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - int min; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - min = TEMP_FROM_REG(data->zone[nr].limit); - data->zone[nr].max_desired = TEMP_TO_REG(val); - data->zone[nr].range = RANGE_TO_REG( - val - min); - lm85_write_value(client, LM85_REG_AFAN_RANGE(nr), - ((data->zone[nr].range & 0x0f) << 4) - | (data->pwm_freq[nr] & 0x07)); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_auto_temp_crit(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct lm85_data *data = lm85_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->zone[nr].critical)); -} - -static ssize_t set_temp_auto_temp_crit(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->zone[nr].critical = TEMP_TO_REG(val); - lm85_write_value(client, LM85_REG_AFAN_CRITICAL(nr), - data->zone[nr].critical); - mutex_unlock(&data->update_lock); - return count; -} - -#define temp_auto(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_off, \ - S_IRUGO | S_IWUSR, show_temp_auto_temp_off, \ - set_temp_auto_temp_off, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_min, \ - S_IRUGO | S_IWUSR, show_temp_auto_temp_min, \ - set_temp_auto_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_max, \ - S_IRUGO | S_IWUSR, show_temp_auto_temp_max, \ - set_temp_auto_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_auto_temp_crit, \ - S_IRUGO | S_IWUSR, show_temp_auto_temp_crit, \ - set_temp_auto_temp_crit, offset - 1); - -temp_auto(1); -temp_auto(2); -temp_auto(3); - -static struct attribute *lm85_attributes[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - - &sensor_dev_attr_pwm1_auto_channels.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_channels.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr, - - &sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr, - &sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr, - &sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr, - &sensor_dev_attr_temp1_auto_temp_max.dev_attr.attr, - &sensor_dev_attr_temp2_auto_temp_max.dev_attr.attr, - &sensor_dev_attr_temp3_auto_temp_max.dev_attr.attr, - &sensor_dev_attr_temp1_auto_temp_crit.dev_attr.attr, - &sensor_dev_attr_temp2_auto_temp_crit.dev_attr.attr, - &sensor_dev_attr_temp3_auto_temp_crit.dev_attr.attr, - - &dev_attr_vrm.attr, - &dev_attr_cpu0_vid.attr, - &dev_attr_alarms.attr, - NULL -}; - -static const struct attribute_group lm85_group = { - .attrs = lm85_attributes, -}; - -static struct attribute *lm85_attributes_minctl[] = { - &sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr, - &sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm85_group_minctl = { - .attrs = lm85_attributes_minctl, -}; - -static struct attribute *lm85_attributes_temp_off[] = { - &sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr, - &sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr, - &sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm85_group_temp_off = { - .attrs = lm85_attributes_temp_off, -}; - -static struct attribute *lm85_attributes_in4[] = { - &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 -}; - -static const struct attribute_group lm85_group_in4 = { - .attrs = lm85_attributes_in4, -}; - -static struct attribute *lm85_attributes_in567[] = { - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm85_group_in567 = { - .attrs = lm85_attributes_in567, -}; - -static void lm85_init_client(struct i2c_client *client) -{ - int value; - - /* Start monitoring if needed */ - value = lm85_read_value(client, LM85_REG_CONFIG); - if (!(value & 0x01)) { - dev_info(&client->dev, "Starting monitoring\n"); - lm85_write_value(client, LM85_REG_CONFIG, value | 0x01); - } - - /* Warn about unusual configuration bits */ - if (value & 0x02) - dev_warn(&client->dev, "Device configuration is locked\n"); - if (!(value & 0x04)) - dev_warn(&client->dev, "Device is not ready\n"); -} - -static int lm85_is_fake(struct i2c_client *client) -{ - /* - * Differenciate between real LM96000 and Winbond WPCD377I. The latter - * emulate the former except that it has no hardware monitoring function - * so the readings are always 0. - */ - int i; - u8 in_temp, fan; - - for (i = 0; i < 8; i++) { - in_temp = i2c_smbus_read_byte_data(client, 0x20 + i); - fan = i2c_smbus_read_byte_data(client, 0x28 + i); - if (in_temp != 0x00 || fan != 0xff) - return 0; - } - - return 1; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - const char *type_name; - int company, verstep; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - /* We need to be able to do byte I/O */ - return -ENODEV; - } - - /* Determine the chip type */ - company = lm85_read_value(client, LM85_REG_COMPANY); - verstep = lm85_read_value(client, LM85_REG_VERSTEP); - - dev_dbg(&adapter->dev, "Detecting device at 0x%02x with " - "COMPANY: 0x%02x and VERSTEP: 0x%02x\n", - address, company, verstep); - - /* All supported chips have the version in common */ - if ((verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC && - (verstep & LM85_VERSTEP_VMASK) != LM85_VERSTEP_GENERIC2) { - dev_dbg(&adapter->dev, - "Autodetection failed: unsupported version\n"); - return -ENODEV; - } - type_name = "lm85"; - - /* Now, refine the detection */ - if (company == LM85_COMPANY_NATIONAL) { - switch (verstep) { - case LM85_VERSTEP_LM85C: - type_name = "lm85c"; - break; - case LM85_VERSTEP_LM85B: - type_name = "lm85b"; - break; - case LM85_VERSTEP_LM96000_1: - case LM85_VERSTEP_LM96000_2: - /* Check for Winbond WPCD377I */ - if (lm85_is_fake(client)) { - dev_dbg(&adapter->dev, - "Found Winbond WPCD377I, ignoring\n"); - return -ENODEV; - } - break; - } - } else if (company == LM85_COMPANY_ANALOG_DEV) { - switch (verstep) { - case LM85_VERSTEP_ADM1027: - type_name = "adm1027"; - break; - case LM85_VERSTEP_ADT7463: - case LM85_VERSTEP_ADT7463C: - type_name = "adt7463"; - break; - case LM85_VERSTEP_ADT7468_1: - case LM85_VERSTEP_ADT7468_2: - type_name = "adt7468"; - break; - } - } else if (company == LM85_COMPANY_SMSC) { - switch (verstep) { - case LM85_VERSTEP_EMC6D100_A0: - case LM85_VERSTEP_EMC6D100_A1: - /* Note: we can't tell a '100 from a '101 */ - type_name = "emc6d100"; - break; - case LM85_VERSTEP_EMC6D102: - type_name = "emc6d102"; - break; - case LM85_VERSTEP_EMC6D103_A0: - case LM85_VERSTEP_EMC6D103_A1: - type_name = "emc6d103"; - break; - case LM85_VERSTEP_EMC6D103S: - type_name = "emc6d103s"; - break; - } - } else { - dev_dbg(&adapter->dev, - "Autodetection failed: unknown vendor\n"); - return -ENODEV; - } - - strlcpy(info->type, type_name, I2C_NAME_SIZE); - - return 0; -} - -static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data) -{ - sysfs_remove_group(&client->dev.kobj, &lm85_group); - if (data->type != emc6d103s) { - sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl); - sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off); - } - if (!data->has_vid5) - sysfs_remove_group(&client->dev.kobj, &lm85_group_in4); - if (data->type == emc6d100) - sysfs_remove_group(&client->dev.kobj, &lm85_group_in567); -} - -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm85_data *data; - int err; - - data = kzalloc(sizeof(struct lm85_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - mutex_init(&data->update_lock); - - /* Fill in the chip specific driver values */ - switch (data->type) { - case adm1027: - case adt7463: - case adt7468: - case emc6d100: - case emc6d102: - case emc6d103: - case emc6d103s: - data->freq_map = adm1027_freq_map; - break; - default: - data->freq_map = lm85_freq_map; - } - - /* Set the VRM version */ - data->vrm = vid_which_vrm(); - - /* Initialize the LM85 chip */ - lm85_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm85_group); - if (err) - goto err_kfree; - - /* minctl and temp_off exist on all chips except emc6d103s */ - if (data->type != emc6d103s) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl); - if (err) - goto err_remove_files; - err = sysfs_create_group(&client->dev.kobj, - &lm85_group_temp_off); - if (err) - goto err_remove_files; - } - - /* - * The ADT7463/68 have an optional VRM 10 mode where pin 21 is used - * as a sixth digital VID input rather than an analog input. - */ - if (data->type == adt7463 || data->type == adt7468) { - u8 vid = lm85_read_value(client, LM85_REG_VID); - if (vid & 0x80) - data->has_vid5 = true; - } - - if (!data->has_vid5) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4); - if (err) - goto err_remove_files; - } - - /* The EMC6D100 has 3 additional voltage inputs */ - if (data->type == emc6d100) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_in567); - if (err) - goto err_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto err_remove_files; - } - - return 0; - - /* Error out and cleanup code */ - err_remove_files: - lm85_remove_files(client, data); - err_kfree: - kfree(data); - return err; -} - -static int lm85_remove(struct i2c_client *client) -{ - struct lm85_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - lm85_remove_files(client, data); - kfree(data); - return 0; -} - - -static int lm85_read_value(struct i2c_client *client, u8 reg) -{ - int res; - - /* What size location is it? */ - switch (reg) { - case LM85_REG_FAN(0): /* Read WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - case LM85_REG_ALARM1: /* Read both bytes at once */ - res = i2c_smbus_read_byte_data(client, reg) & 0xff; - res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; - break; - default: /* Read BYTE data */ - res = i2c_smbus_read_byte_data(client, reg); - break; - } - - return res; -} - -static void lm85_write_value(struct i2c_client *client, u8 reg, int value) -{ - switch (reg) { - case LM85_REG_FAN(0): /* Write WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - /* NOTE: ALARM is read only, so not included here */ - i2c_smbus_write_byte_data(client, reg, value & 0xff); - i2c_smbus_write_byte_data(client, reg + 1, value >> 8); - break; - default: /* Write BYTE data */ - i2c_smbus_write_byte_data(client, reg, value); - break; - } -} - -static struct lm85_data *lm85_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (!data->valid || - time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { - /* Things that change quickly */ - dev_dbg(&client->dev, "Reading sensor values\n"); - - /* - * Have to read extended bits first to "freeze" the - * more significant bits that are read later. - * There are 2 additional resolution bits per channel and we - * have room for 4, so we shift them to the left. - */ - if (data->type == adm1027 || data->type == adt7463 || - data->type == adt7468) { - int ext1 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC2); - int val = (ext1 << 8) + ext2; - - for (i = 0; i <= 4; i++) - data->in_ext[i] = - ((val >> (i * 2)) & 0x03) << 2; - - for (i = 0; i <= 2; i++) - data->temp_ext[i] = - (val >> ((i + 4) * 2)) & 0x0c; - } - - data->vid = lm85_read_value(client, LM85_REG_VID); - - for (i = 0; i <= 3; ++i) { - data->in[i] = - lm85_read_value(client, LM85_REG_IN(i)); - data->fan[i] = - lm85_read_value(client, LM85_REG_FAN(i)); - } - - if (!data->has_vid5) - data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); - - if (data->type == adt7468) - data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); - - for (i = 0; i <= 2; ++i) { - data->temp[i] = - lm85_read_value(client, LM85_REG_TEMP(i)); - data->pwm[i] = - lm85_read_value(client, LM85_REG_PWM(i)); - - if (IS_ADT7468_OFF64(data)) - data->temp[i] -= 64; - } - - data->alarms = lm85_read_value(client, LM85_REG_ALARM1); - - if (data->type == emc6d100) { - /* Three more voltage sensors */ - for (i = 5; i <= 7; ++i) { - data->in[i] = lm85_read_value(client, - EMC6D100_REG_IN(i)); - } - /* More alarm bits */ - data->alarms |= lm85_read_value(client, - EMC6D100_REG_ALARM3) << 16; - } else if (data->type == emc6d102 || data->type == emc6d103 || - data->type == emc6d103s) { - /* - * Have to read LSB bits after the MSB ones because - * the reading of the MSB bits has frozen the - * LSBs (backward from the ADM1027). - */ - int ext1 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC2); - int ext3 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC3); - int ext4 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC4); - data->in_ext[0] = ext3 & 0x0f; - data->in_ext[1] = ext4 & 0x0f; - data->in_ext[2] = ext4 >> 4; - data->in_ext[3] = ext3 >> 4; - data->in_ext[4] = ext2 >> 4; - - data->temp_ext[0] = ext1 & 0x0f; - data->temp_ext[1] = ext2 & 0x0f; - data->temp_ext[2] = ext1 >> 4; - } - - data->last_reading = jiffies; - } /* last_reading */ - - if (!data->valid || - time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { - /* Things that don't change often */ - dev_dbg(&client->dev, "Reading config values\n"); - - for (i = 0; i <= 3; ++i) { - data->in_min[i] = - lm85_read_value(client, LM85_REG_IN_MIN(i)); - data->in_max[i] = - lm85_read_value(client, LM85_REG_IN_MAX(i)); - data->fan_min[i] = - lm85_read_value(client, LM85_REG_FAN_MIN(i)); - } - - if (!data->has_vid5) { - data->in_min[4] = lm85_read_value(client, - LM85_REG_IN_MIN(4)); - data->in_max[4] = lm85_read_value(client, - LM85_REG_IN_MAX(4)); - } - - if (data->type == emc6d100) { - for (i = 5; i <= 7; ++i) { - data->in_min[i] = lm85_read_value(client, - EMC6D100_REG_IN_MIN(i)); - data->in_max[i] = lm85_read_value(client, - EMC6D100_REG_IN_MAX(i)); - } - } - - for (i = 0; i <= 2; ++i) { - int val; - - data->temp_min[i] = - lm85_read_value(client, LM85_REG_TEMP_MIN(i)); - data->temp_max[i] = - lm85_read_value(client, LM85_REG_TEMP_MAX(i)); - - data->autofan[i].config = - lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); - val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); - data->pwm_freq[i] = val & 0x07; - data->zone[i].range = val >> 4; - data->autofan[i].min_pwm = - lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); - data->zone[i].limit = - lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); - data->zone[i].critical = - lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); - - if (IS_ADT7468_OFF64(data)) { - data->temp_min[i] -= 64; - data->temp_max[i] -= 64; - data->zone[i].limit -= 64; - data->zone[i].critical -= 64; - } - } - - if (data->type != emc6d103s) { - i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); - data->autofan[0].min_off = (i & 0x20) != 0; - data->autofan[1].min_off = (i & 0x40) != 0; - data->autofan[2].min_off = (i & 0x80) != 0; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST1); - data->zone[0].hyst = i >> 4; - data->zone[1].hyst = i & 0x0f; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST2); - data->zone[2].hyst = i >> 4; - } - - data->last_config = jiffies; - } /* last_config */ - - data->valid = 1; - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(lm85_driver); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Philip Pokorny , " - "Margit Schubert-While , " - "Justin Thiessen "); -MODULE_DESCRIPTION("LM85-B, LM85-C driver"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm87.c b/ANDROID_3.4.5/drivers/hwmon/lm87.c deleted file mode 100644 index 314d147b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm87.c +++ /dev/null @@ -1,1021 +0,0 @@ -/* - * lm87.c - * - * Copyright (C) 2000 Frodo Looijaard - * Philip Edelbrock - * Stephen Rousset - * Dan Eaton - * Copyright (C) 2004-2008 Jean Delvare - * - * Original port to Linux 2.6 by Jeff Oliver. - * - * The LM87 is a sensor chip made by National Semiconductor. It monitors up - * to 8 voltages (including its own power source), up to three temperatures - * (its own plus up to two external ones) and up to two fans. The default - * configuration is 6 voltages, two temperatures and two fans (see below). - * Voltages are scaled internally with ratios such that the nominal value of - * each voltage correspond to a register value of 192 (which means a - * resolution of about 0.5% of the nominal value). Temperature values are - * reported with a 1 deg resolution and a 3-4 deg accuracy. Complete - * datasheet can be obtained from National's website at: - * http://www.national.com/pf/LM/LM87.html - * - * Some functions share pins, so not all functions are available at the same - * time. Which are depends on the hardware setup. This driver normally - * assumes that firmware configured the chip correctly. Where this is not - * the case, platform code must set the I2C client's platform_data to point - * to a u8 value to be written to the channel register. - * For reference, here is the list of exclusive functions: - * - in0+in5 (default) or temp3 - * - fan1 (default) or in6 - * - fan2 (default) or in7 - * - VID lines (default) or IRQ lines (not handled by this driver) - * - * The LM87 additionally features an analog output, supposedly usable to - * control the speed of a fan. All new chips use pulse width modulation - * instead. The LM87 is the only hardware monitoring chipset I know of - * which uses amplitude modulation. Be careful when using this feature. - * - * This driver also supports the ADM1024, a sensor chip made by Analog - * Devices. That chip is fully compatible with the LM87. Complete - * datasheet can be obtained from Analog's website at: - * http://www.analog.com/en/prod/0,2877,ADM1024,00.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - * LM87 has three possible addresses: 0x2c, 0x2d and 0x2e. - */ - -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -enum chips { lm87, adm1024 }; - -/* - * The LM87 registers - */ - -/* nr in 0..5 */ -#define LM87_REG_IN(nr) (0x20 + (nr)) -#define LM87_REG_IN_MAX(nr) (0x2B + (nr) * 2) -#define LM87_REG_IN_MIN(nr) (0x2C + (nr) * 2) -/* nr in 0..1 */ -#define LM87_REG_AIN(nr) (0x28 + (nr)) -#define LM87_REG_AIN_MIN(nr) (0x1A + (nr)) -#define LM87_REG_AIN_MAX(nr) (0x3B + (nr)) - -static u8 LM87_REG_TEMP[3] = { 0x27, 0x26, 0x20 }; -static u8 LM87_REG_TEMP_HIGH[3] = { 0x39, 0x37, 0x2B }; -static u8 LM87_REG_TEMP_LOW[3] = { 0x3A, 0x38, 0x2C }; - -#define LM87_REG_TEMP_HW_INT_LOCK 0x13 -#define LM87_REG_TEMP_HW_EXT_LOCK 0x14 -#define LM87_REG_TEMP_HW_INT 0x17 -#define LM87_REG_TEMP_HW_EXT 0x18 - -/* nr in 0..1 */ -#define LM87_REG_FAN(nr) (0x28 + (nr)) -#define LM87_REG_FAN_MIN(nr) (0x3B + (nr)) -#define LM87_REG_AOUT 0x19 - -#define LM87_REG_CONFIG 0x40 -#define LM87_REG_CHANNEL_MODE 0x16 -#define LM87_REG_VID_FAN_DIV 0x47 -#define LM87_REG_VID4 0x49 - -#define LM87_REG_ALARMS1 0x41 -#define LM87_REG_ALARMS2 0x42 - -#define LM87_REG_COMPANY_ID 0x3E -#define LM87_REG_REVISION 0x3F - -/* - * Conversions and various macros - * The LM87 uses signed 8-bit values for temperatures. - */ - -#define IN_FROM_REG(reg, scale) (((reg) * (scale) + 96) / 192) -#define IN_TO_REG(val, scale) ((val) <= 0 ? 0 : \ - (val) * 192 >= (scale) * 255 ? 255 : \ - ((val) * 192 + (scale) / 2) / (scale)) - -#define TEMP_FROM_REG(reg) ((reg) * 1000) -#define TEMP_TO_REG(val) ((val) <= -127500 ? -128 : \ - (val) >= 126500 ? 127 : \ - (((val) < 0 ? (val) - 500 : \ - (val) + 500) / 1000)) - -#define FAN_FROM_REG(reg, div) ((reg) == 255 || (reg) == 0 ? 0 : \ - (1350000 + (reg)*(div) / 2) / ((reg) * (div))) -#define FAN_TO_REG(val, div) ((val) * (div) * 255 <= 1350000 ? 255 : \ - (1350000 + (val)*(div) / 2) / ((val) * (div))) - -#define FAN_DIV_FROM_REG(reg) (1 << (reg)) - -/* analog out is 9.80mV/LSB */ -#define AOUT_FROM_REG(reg) (((reg) * 98 + 5) / 10) -#define AOUT_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 2500 ? 255 : \ - ((val) * 10 + 49) / 98) - -/* nr in 0..1 */ -#define CHAN_NO_FAN(nr) (1 << (nr)) -#define CHAN_TEMP3 (1 << 2) -#define CHAN_VCC_5V (1 << 3) -#define CHAN_NO_VID (1 << 7) - -/* - * Client data (each client gets its own) - */ - -struct lm87_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 channel; /* register value */ - u8 config; /* original register value */ - - u8 in[8]; /* register value */ - u8 in_max[8]; /* register value */ - u8 in_min[8]; /* register value */ - u16 in_scale[8]; - - s8 temp[3]; /* register value */ - s8 temp_high[3]; /* register value */ - s8 temp_low[3]; /* register value */ - s8 temp_crit_int; /* min of two register values */ - s8 temp_crit_ext; /* min of two register values */ - - u8 fan[2]; /* register value */ - u8 fan_min[2]; /* register value */ - u8 fan_div[2]; /* register value, shifted right */ - u8 aout; /* register value */ - - u16 alarms; /* register values, combined */ - u8 vid; /* register values, combined */ - u8 vrm; -}; - -static inline int lm87_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static inline int lm87_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -static struct lm87_data *lm87_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int i, j; - - dev_dbg(&client->dev, "Updating data.\n"); - - i = (data->channel & CHAN_TEMP3) ? 1 : 0; - j = (data->channel & CHAN_TEMP3) ? 5 : 6; - for (; i < j; i++) { - data->in[i] = lm87_read_value(client, - LM87_REG_IN(i)); - data->in_min[i] = lm87_read_value(client, - LM87_REG_IN_MIN(i)); - data->in_max[i] = lm87_read_value(client, - LM87_REG_IN_MAX(i)); - } - - for (i = 0; i < 2; i++) { - if (data->channel & CHAN_NO_FAN(i)) { - data->in[6+i] = lm87_read_value(client, - LM87_REG_AIN(i)); - data->in_max[6+i] = lm87_read_value(client, - LM87_REG_AIN_MAX(i)); - data->in_min[6+i] = lm87_read_value(client, - LM87_REG_AIN_MIN(i)); - - } else { - data->fan[i] = lm87_read_value(client, - LM87_REG_FAN(i)); - data->fan_min[i] = lm87_read_value(client, - LM87_REG_FAN_MIN(i)); - } - } - - j = (data->channel & CHAN_TEMP3) ? 3 : 2; - for (i = 0 ; i < j; i++) { - data->temp[i] = lm87_read_value(client, - LM87_REG_TEMP[i]); - data->temp_high[i] = lm87_read_value(client, - LM87_REG_TEMP_HIGH[i]); - data->temp_low[i] = lm87_read_value(client, - LM87_REG_TEMP_LOW[i]); - } - - i = lm87_read_value(client, LM87_REG_TEMP_HW_INT_LOCK); - j = lm87_read_value(client, LM87_REG_TEMP_HW_INT); - data->temp_crit_int = min(i, j); - - i = lm87_read_value(client, LM87_REG_TEMP_HW_EXT_LOCK); - j = lm87_read_value(client, LM87_REG_TEMP_HW_EXT); - data->temp_crit_ext = min(i, j); - - i = lm87_read_value(client, LM87_REG_VID_FAN_DIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = (i >> 6) & 0x03; - data->vid = (i & 0x0F) - | (lm87_read_value(client, LM87_REG_VID4) & 0x01) - << 4; - - data->alarms = lm87_read_value(client, LM87_REG_ALARMS1) - | (lm87_read_value(client, LM87_REG_ALARMS2) - << 8); - data->aout = lm87_read_value(client, LM87_REG_AOUT); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Sysfs stuff - */ - -static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%u\n", IN_FROM_REG(data->in[nr], - data->in_scale[nr])); -} - -static ssize_t show_in_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[nr], - data->in_scale[nr])); -} - -static ssize_t show_in_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[nr], - data->in_scale[nr])); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val, data->in_scale[nr]); - lm87_write_value(client, nr < 6 ? LM87_REG_IN_MIN(nr) : - LM87_REG_AIN_MIN(nr - 6), data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val, data->in_scale[nr]); - lm87_write_value(client, nr < 6 ? LM87_REG_IN_MAX(nr) : - LM87_REG_AIN_MAX(nr - 6), data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define set_in(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in_input, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset) -set_in(0); -set_in(1); -set_in(2); -set_in(3); -set_in(4); -set_in(5); -set_in(6); -set_in(7); - -static ssize_t show_temp_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); -} - -static ssize_t show_temp_low(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%d\n", - TEMP_FROM_REG(data->temp_low[nr])); -} - -static ssize_t show_temp_high(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%d\n", - TEMP_FROM_REG(data->temp_high[nr])); -} - -static ssize_t set_temp_low(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_low[nr] = TEMP_TO_REG(val); - lm87_write_value(client, LM87_REG_TEMP_LOW[nr], data->temp_low[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_high(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_high[nr] = TEMP_TO_REG(val); - lm87_write_value(client, LM87_REG_TEMP_HIGH[nr], data->temp_high[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define set_temp(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp_input, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_high, set_temp_high, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_low, set_temp_low, offset - 1) -set_temp(1); -set_temp(2); -set_temp(3); - -static ssize_t show_temp_crit_int(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_int)); -} - -static ssize_t show_temp_crit_ext(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_crit_ext)); -} - -static DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit_int, NULL); -static DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit_ext, NULL); -static DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit_ext, NULL); - -static ssize_t show_fan_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - FAN_DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - FAN_DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int nr = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%d\n", - FAN_DIV_FROM_REG(data->fan_div[nr])); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, - FAN_DIV_FROM_REG(data->fan_div[nr])); - lm87_write_value(client, LM87_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan clock divider. This follows the principle - * of least surprise; the user doesn't expect the fan minimum to change just - * because the divider changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - int nr = to_sensor_dev_attr(attr)->index; - long val; - int err; - unsigned long min; - u8 reg; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - FAN_DIV_FROM_REG(data->fan_div[nr])); - - switch (val) { - case 1: - data->fan_div[nr] = 0; - break; - case 2: - data->fan_div[nr] = 1; - break; - case 4: - data->fan_div[nr] = 2; - break; - case 8: - data->fan_div[nr] = 3; - break; - default: - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - reg = lm87_read_value(client, LM87_REG_VID_FAN_DIV); - switch (nr) { - case 0: - reg = (reg & 0xCF) | (data->fan_div[0] << 4); - break; - case 1: - reg = (reg & 0x3F) | (data->fan_div[1] << 6); - break; - } - lm87_write_value(client, LM87_REG_VID_FAN_DIV, reg); - - data->fan_min[nr] = FAN_TO_REG(min, val); - lm87_write_value(client, LM87_REG_FAN_MIN(nr), - data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -#define set_fan(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan_input, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1) -set_fan(1); -set_fan(2); - -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm87_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->vrm); -} -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct lm87_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - data->vrm = val; - return count; -} -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); - -static ssize_t show_aout(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - return sprintf(buf, "%d\n", AOUT_FROM_REG(data->aout)); -} -static ssize_t set_aout(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm87_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->aout = AOUT_TO_REG(val); - lm87_write_value(client, LM87_REG_AOUT, data->aout); - mutex_unlock(&data->update_lock); - return count; -} -static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm87_data *data = lm87_update_device(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); -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(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 14); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 15); - -/* - * Real code - */ - -static struct attribute *lm87_attributes[] = { - &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, - &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, - &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, - &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, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &dev_attr_temp1_crit.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &dev_attr_temp2_crit.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - - &dev_attr_alarms.attr, - &dev_attr_aout_output.attr, - - NULL -}; - -static const struct attribute_group lm87_group = { - .attrs = lm87_attributes, -}; - -static struct attribute *lm87_attributes_in6[] = { - &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 -}; - -static const struct attribute_group lm87_group_in6 = { - .attrs = lm87_attributes_in6, -}; - -static struct attribute *lm87_attributes_fan1[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm87_group_fan1 = { - .attrs = lm87_attributes_fan1, -}; - -static struct attribute *lm87_attributes_in7[] = { - &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 -}; - -static const struct attribute_group lm87_group_in7 = { - .attrs = lm87_attributes_in7, -}; - -static struct attribute *lm87_attributes_fan2[] = { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm87_group_fan2 = { - .attrs = lm87_attributes_fan2, -}; - -static struct attribute *lm87_attributes_temp3[] = { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &dev_attr_temp3_crit.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm87_group_temp3 = { - .attrs = lm87_attributes_temp3, -}; - -static struct attribute *lm87_attributes_in0_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, - &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 -}; - -static const struct attribute_group lm87_group_in0_5 = { - .attrs = lm87_attributes_in0_5, -}; - -static struct attribute *lm87_attributes_vid[] = { - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - NULL -}; - -static const struct attribute_group lm87_group_vid = { - .attrs = lm87_attributes_vid, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm87_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - const char *name; - u8 cid, rev; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - if (lm87_read_value(client, LM87_REG_CONFIG) & 0x80) - return -ENODEV; - - /* Now, we do the remaining detection. */ - cid = lm87_read_value(client, LM87_REG_COMPANY_ID); - rev = lm87_read_value(client, LM87_REG_REVISION); - - if (cid == 0x02 /* National Semiconductor */ - && (rev >= 0x01 && rev <= 0x08)) - name = "lm87"; - else if (cid == 0x41 /* Analog Devices */ - && (rev & 0xf0) == 0x10) - name = "adm1024"; - else { - dev_dbg(&adapter->dev, "LM87 detection failed at 0x%02x\n", - client->addr); - return -ENODEV; - } - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static void lm87_remove_files(struct i2c_client *client) -{ - struct device *dev = &client->dev; - - sysfs_remove_group(&dev->kobj, &lm87_group); - sysfs_remove_group(&dev->kobj, &lm87_group_in6); - sysfs_remove_group(&dev->kobj, &lm87_group_fan1); - sysfs_remove_group(&dev->kobj, &lm87_group_in7); - sysfs_remove_group(&dev->kobj, &lm87_group_fan2); - sysfs_remove_group(&dev->kobj, &lm87_group_temp3); - sysfs_remove_group(&dev->kobj, &lm87_group_in0_5); - sysfs_remove_group(&dev->kobj, &lm87_group_vid); -} - -static void lm87_init_client(struct i2c_client *client) -{ - struct lm87_data *data = i2c_get_clientdata(client); - - if (client->dev.platform_data) { - data->channel = *(u8 *)client->dev.platform_data; - lm87_write_value(client, - LM87_REG_CHANNEL_MODE, data->channel); - } else { - data->channel = lm87_read_value(client, LM87_REG_CHANNEL_MODE); - } - data->config = lm87_read_value(client, LM87_REG_CONFIG) & 0x6F; - - if (!(data->config & 0x01)) { - int i; - - /* Limits are left uninitialized after power-up */ - for (i = 1; i < 6; i++) { - lm87_write_value(client, LM87_REG_IN_MIN(i), 0x00); - lm87_write_value(client, LM87_REG_IN_MAX(i), 0xFF); - } - for (i = 0; i < 2; i++) { - lm87_write_value(client, LM87_REG_TEMP_HIGH[i], 0x7F); - lm87_write_value(client, LM87_REG_TEMP_LOW[i], 0x00); - lm87_write_value(client, LM87_REG_AIN_MIN(i), 0x00); - lm87_write_value(client, LM87_REG_AIN_MAX(i), 0xFF); - } - if (data->channel & CHAN_TEMP3) { - lm87_write_value(client, LM87_REG_TEMP_HIGH[2], 0x7F); - lm87_write_value(client, LM87_REG_TEMP_LOW[2], 0x00); - } else { - lm87_write_value(client, LM87_REG_IN_MIN(0), 0x00); - lm87_write_value(client, LM87_REG_IN_MAX(0), 0xFF); - } - } - - /* Make sure Start is set and INT#_Clear is clear */ - if ((data->config & 0x09) != 0x01) - lm87_write_value(client, LM87_REG_CONFIG, - (data->config & 0x77) | 0x01); -} - -static int lm87_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct lm87_data *data; - int err; - - data = kzalloc(sizeof(struct lm87_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Initialize the LM87 chip */ - lm87_init_client(client); - - data->in_scale[0] = 2500; - data->in_scale[1] = 2700; - data->in_scale[2] = (data->channel & CHAN_VCC_5V) ? 5000 : 3300; - data->in_scale[3] = 5000; - data->in_scale[4] = 12000; - data->in_scale[5] = 2700; - data->in_scale[6] = 1875; - data->in_scale[7] = 1875; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm87_group); - if (err) - goto exit_free; - - if (data->channel & CHAN_NO_FAN(0)) { - err = sysfs_create_group(&client->dev.kobj, &lm87_group_in6); - if (err) - goto exit_remove; - } else { - err = sysfs_create_group(&client->dev.kobj, &lm87_group_fan1); - if (err) - goto exit_remove; - } - - if (data->channel & CHAN_NO_FAN(1)) { - err = sysfs_create_group(&client->dev.kobj, &lm87_group_in7); - if (err) - goto exit_remove; - } else { - err = sysfs_create_group(&client->dev.kobj, &lm87_group_fan2); - if (err) - goto exit_remove; - } - - if (data->channel & CHAN_TEMP3) { - err = sysfs_create_group(&client->dev.kobj, &lm87_group_temp3); - if (err) - goto exit_remove; - } else { - err = sysfs_create_group(&client->dev.kobj, &lm87_group_in0_5); - if (err) - goto exit_remove; - } - - if (!(data->channel & CHAN_NO_VID)) { - data->vrm = vid_which_vrm(); - err = sysfs_create_group(&client->dev.kobj, &lm87_group_vid); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - lm87_remove_files(client); -exit_free: - lm87_write_value(client, LM87_REG_CONFIG, data->config); - kfree(data); -exit: - return err; -} - -static int lm87_remove(struct i2c_client *client) -{ - struct lm87_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - lm87_remove_files(client); - - lm87_write_value(client, LM87_REG_CONFIG, data->config); - kfree(data); - return 0; -} - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id lm87_id[] = { - { "lm87", lm87 }, - { "adm1024", adm1024 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm87_id); - -static struct i2c_driver lm87_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm87", - }, - .probe = lm87_probe, - .remove = lm87_remove, - .id_table = lm87_id, - .detect = lm87_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm87_driver); - -MODULE_AUTHOR("Jean Delvare and others"); -MODULE_DESCRIPTION("LM87 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm90.c b/ANDROID_3.4.5/drivers/hwmon/lm90.c deleted file mode 100644 index 22b14a68..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm90.c +++ /dev/null @@ -1,1553 +0,0 @@ -/* - * lm90.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2003-2010 Jean Delvare - * - * Based on the lm83 driver. The LM90 is a sensor chip made by National - * Semiconductor. It reports up to two temperatures (its own plus up to - * one external one) with a 0.125 deg resolution (1 deg for local - * temperature) and a 3-4 deg accuracy. - * - * This driver also supports the LM89 and LM99, two other sensor chips - * made by National Semiconductor. Both have an increased remote - * temperature measurement accuracy (1 degree), and the LM99 - * additionally shifts remote temperatures (measured and limits) by 16 - * degrees, which allows for higher temperatures measurement. - * Note that there is no way to differentiate between both chips. - * When device is auto-detected, the driver will assume an LM99. - * - * This driver also supports the LM86, another sensor chip made by - * National Semiconductor. It is exactly similar to the LM90 except it - * has a higher accuracy. - * - * This driver also supports the ADM1032, a sensor chip made by Analog - * Devices. That chip is similar to the LM90, with a few differences - * that are not handled by this driver. Among others, it has a higher - * accuracy than the LM90, much like the LM86 does. - * - * This driver also supports the MAX6657, MAX6658 and MAX6659 sensor - * chips made by Maxim. These chips are similar to the LM86. - * Note that there is no easy way to differentiate between the three - * variants. We use the device address to detect MAX6659, which will result - * in a detection as max6657 if it is on address 0x4c. The extra address - * and features of the MAX6659 are only supported if the chip is configured - * explicitly as max6659, or if its address is not 0x4c. - * These chips lack the remote temperature offset feature. - * - * This driver also supports the MAX6646, MAX6647, MAX6648, MAX6649 and - * MAX6692 chips made by Maxim. These are again similar to the LM86, - * but they use unsigned temperature values and can report temperatures - * from 0 to 145 degrees. - * - * This driver also supports the MAX6680 and MAX6681, two other sensor - * chips made by Maxim. These are quite similar to the other Maxim - * chips. The MAX6680 and MAX6681 only differ in the pinout so they can - * be treated identically. - * - * This driver also supports the MAX6695 and MAX6696, two other sensor - * chips made by Maxim. These are also quite similar to other Maxim - * chips, but support three temperature sensors instead of two. MAX6695 - * and MAX6696 only differ in the pinout so they can be treated identically. - * - * This driver also supports ADT7461 and ADT7461A from Analog Devices as well as - * NCT1008 from ON Semiconductor. The chips are supported in both compatibility - * and extended mode. They are mostly compatible with LM90 except for a data - * format difference for the temperature value registers. - * - * This driver also supports the SA56004 from Philips. This device is - * pin-compatible with the LM86, the ED/EDP parts are also address-compatible. - * - * This driver also supports the G781 from GMT. This device is compatible - * with the ADM1032. - * - * Since the LM90 was the first chipset supported by this driver, most - * comments will refer to this chipset, but are actually general and - * concern all supported chipsets, unless mentioned otherwise. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Addresses to scan - * Address is fully defined internally and cannot be changed except for - * MAX6659, MAX6680 and MAX6681. - * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, ADT7461A, MAX6649, - * MAX6657, MAX6658, NCT1008 and W83L771 have address 0x4c. - * ADM1032-2, ADT7461-2, ADT7461A-2, LM89-1, LM99-1, MAX6646, and NCT1008D - * have address 0x4d. - * MAX6647 has address 0x4e. - * MAX6659 can have address 0x4c, 0x4d or 0x4e. - * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, - * 0x4c, 0x4d or 0x4e. - * SA56004 can have address 0x48 through 0x4F. - */ - -static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x48, 0x49, 0x4a, 0x4b, 0x4c, - 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; - -enum chips { lm90, adm1032, lm99, lm86, max6657, max6659, adt7461, max6680, - max6646, w83l771, max6696, sa56004, g781 }; - -/* - * The LM90 registers - */ - -#define LM90_REG_R_MAN_ID 0xFE -#define LM90_REG_R_CHIP_ID 0xFF -#define LM90_REG_R_CONFIG1 0x03 -#define LM90_REG_W_CONFIG1 0x09 -#define LM90_REG_R_CONFIG2 0xBF -#define LM90_REG_W_CONFIG2 0xBF -#define LM90_REG_R_CONVRATE 0x04 -#define LM90_REG_W_CONVRATE 0x0A -#define LM90_REG_R_STATUS 0x02 -#define LM90_REG_R_LOCAL_TEMP 0x00 -#define LM90_REG_R_LOCAL_HIGH 0x05 -#define LM90_REG_W_LOCAL_HIGH 0x0B -#define LM90_REG_R_LOCAL_LOW 0x06 -#define LM90_REG_W_LOCAL_LOW 0x0C -#define LM90_REG_R_LOCAL_CRIT 0x20 -#define LM90_REG_W_LOCAL_CRIT 0x20 -#define LM90_REG_R_REMOTE_TEMPH 0x01 -#define LM90_REG_R_REMOTE_TEMPL 0x10 -#define LM90_REG_R_REMOTE_OFFSH 0x11 -#define LM90_REG_W_REMOTE_OFFSH 0x11 -#define LM90_REG_R_REMOTE_OFFSL 0x12 -#define LM90_REG_W_REMOTE_OFFSL 0x12 -#define LM90_REG_R_REMOTE_HIGHH 0x07 -#define LM90_REG_W_REMOTE_HIGHH 0x0D -#define LM90_REG_R_REMOTE_HIGHL 0x13 -#define LM90_REG_W_REMOTE_HIGHL 0x13 -#define LM90_REG_R_REMOTE_LOWH 0x08 -#define LM90_REG_W_REMOTE_LOWH 0x0E -#define LM90_REG_R_REMOTE_LOWL 0x14 -#define LM90_REG_W_REMOTE_LOWL 0x14 -#define LM90_REG_R_REMOTE_CRIT 0x19 -#define LM90_REG_W_REMOTE_CRIT 0x19 -#define LM90_REG_R_TCRIT_HYST 0x21 -#define LM90_REG_W_TCRIT_HYST 0x21 - -/* MAX6646/6647/6649/6657/6658/6659/6695/6696 registers */ - -#define MAX6657_REG_R_LOCAL_TEMPL 0x11 -#define MAX6696_REG_R_STATUS2 0x12 -#define MAX6659_REG_R_REMOTE_EMERG 0x16 -#define MAX6659_REG_W_REMOTE_EMERG 0x16 -#define MAX6659_REG_R_LOCAL_EMERG 0x17 -#define MAX6659_REG_W_LOCAL_EMERG 0x17 - -/* SA56004 registers */ - -#define SA56004_REG_R_LOCAL_TEMPL 0x22 - -#define LM90_DEF_CONVRATE_RVAL 6 /* Def conversion rate register value */ -#define LM90_MAX_CONVRATE_MS 16000 /* Maximum conversion rate in ms */ - -/* - * Device flags - */ -#define LM90_FLAG_ADT7461_EXT (1 << 0) /* ADT7461 extended mode */ -/* Device features */ -#define LM90_HAVE_OFFSET (1 << 1) /* temperature offset register */ -#define LM90_HAVE_REM_LIMIT_EXT (1 << 3) /* extended remote limit */ -#define LM90_HAVE_EMERGENCY (1 << 4) /* 3rd upper (emergency) limit */ -#define LM90_HAVE_EMERGENCY_ALARM (1 << 5)/* emergency alarm */ -#define LM90_HAVE_TEMP3 (1 << 6) /* 3rd temperature sensor */ -#define LM90_HAVE_BROKEN_ALERT (1 << 7) /* Broken alert */ - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id lm90_id[] = { - { "adm1032", adm1032 }, - { "adt7461", adt7461 }, - { "adt7461a", adt7461 }, - { "g781", g781 }, - { "lm90", lm90 }, - { "lm86", lm86 }, - { "lm89", lm86 }, - { "lm99", lm99 }, - { "max6646", max6646 }, - { "max6647", max6646 }, - { "max6649", max6646 }, - { "max6657", max6657 }, - { "max6658", max6657 }, - { "max6659", max6659 }, - { "max6680", max6680 }, - { "max6681", max6680 }, - { "max6695", max6696 }, - { "max6696", max6696 }, - { "nct1008", adt7461 }, - { "w83l771", w83l771 }, - { "sa56004", sa56004 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm90_id); - -/* - * chip type specific parameters - */ -struct lm90_params { - u32 flags; /* Capabilities */ - u16 alert_alarms; /* Which alarm bits trigger ALERT# */ - /* Upper 8 bits for max6695/96 */ - u8 max_convrate; /* Maximum conversion rate register value */ - u8 reg_local_ext; /* Extended local temp register (optional) */ -}; - -static const struct lm90_params lm90_params[] = { - [adm1032] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT - | LM90_HAVE_BROKEN_ALERT, - .alert_alarms = 0x7c, - .max_convrate = 10, - }, - [adt7461] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT - | LM90_HAVE_BROKEN_ALERT, - .alert_alarms = 0x7c, - .max_convrate = 10, - }, - [g781] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT - | LM90_HAVE_BROKEN_ALERT, - .alert_alarms = 0x7c, - .max_convrate = 8, - }, - [lm86] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, - .alert_alarms = 0x7b, - .max_convrate = 9, - }, - [lm90] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, - .alert_alarms = 0x7b, - .max_convrate = 9, - }, - [lm99] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, - .alert_alarms = 0x7b, - .max_convrate = 9, - }, - [max6646] = { - .alert_alarms = 0x7c, - .max_convrate = 6, - .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, - }, - [max6657] = { - .alert_alarms = 0x7c, - .max_convrate = 8, - .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, - }, - [max6659] = { - .flags = LM90_HAVE_EMERGENCY, - .alert_alarms = 0x7c, - .max_convrate = 8, - .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, - }, - [max6680] = { - .flags = LM90_HAVE_OFFSET, - .alert_alarms = 0x7c, - .max_convrate = 7, - }, - [max6696] = { - .flags = LM90_HAVE_EMERGENCY - | LM90_HAVE_EMERGENCY_ALARM | LM90_HAVE_TEMP3, - .alert_alarms = 0x187c, - .max_convrate = 6, - .reg_local_ext = MAX6657_REG_R_LOCAL_TEMPL, - }, - [w83l771] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, - .alert_alarms = 0x7c, - .max_convrate = 8, - }, - [sa56004] = { - .flags = LM90_HAVE_OFFSET | LM90_HAVE_REM_LIMIT_EXT, - .alert_alarms = 0x7b, - .max_convrate = 9, - .reg_local_ext = SA56004_REG_R_LOCAL_TEMPL, - }, -}; - -/* - * Client data (each client gets its own) - */ - -struct lm90_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - int kind; - u32 flags; - - int update_interval; /* in milliseconds */ - - u8 config_orig; /* Original configuration register value */ - u8 convrate_orig; /* Original conversion rate register value */ - u16 alert_alarms; /* Which alarm bits trigger ALERT# */ - /* Upper 8 bits for max6695/96 */ - u8 max_convrate; /* Maximum conversion rate */ - u8 reg_local_ext; /* local extension register offset */ - - /* registers values */ - s8 temp8[8]; /* 0: local low limit - * 1: local high limit - * 2: local critical limit - * 3: remote critical limit - * 4: local emergency limit (max6659 and max6695/96) - * 5: remote emergency limit (max6659 and max6695/96) - * 6: remote 2 critical limit (max6695/96 only) - * 7: remote 2 emergency limit (max6695/96 only) - */ - s16 temp11[8]; /* 0: remote input - * 1: remote low limit - * 2: remote high limit - * 3: remote offset (except max6646, max6657/58/59, - * and max6695/96) - * 4: local input - * 5: remote 2 input (max6695/96 only) - * 6: remote 2 low limit (max6695/96 only) - * 7: remote 2 high limit (max6695/96 only) - */ - u8 temp_hyst; - u16 alarms; /* bitvector (upper 8 bits for max6695/96) */ -}; - -/* - * Support functions - */ - -/* - * The ADM1032 supports PEC but not on write byte transactions, so we need - * to explicitly ask for a transaction without PEC. - */ -static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value) -{ - return i2c_smbus_xfer(client->adapter, client->addr, - client->flags & ~I2C_CLIENT_PEC, - I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL); -} - -/* - * It is assumed that client->update_lock is held (unless we are in - * detection or initialization steps). This matters when PEC is enabled, - * because we don't want the address pointer to change between the write - * byte and the read byte transactions. - */ -static int lm90_read_reg(struct i2c_client *client, u8 reg, u8 *value) -{ - int err; - - if (client->flags & I2C_CLIENT_PEC) { - err = adm1032_write_byte(client, reg); - if (err >= 0) - err = i2c_smbus_read_byte(client); - } else - err = i2c_smbus_read_byte_data(client, reg); - - if (err < 0) { - dev_warn(&client->dev, "Register %#02x read failed (%d)\n", - reg, err); - return err; - } - *value = err; - - return 0; -} - -static int lm90_read16(struct i2c_client *client, u8 regh, u8 regl, u16 *value) -{ - int err; - u8 oldh, newh, l; - - /* - * There is a trick here. We have to read two registers to have the - * sensor temperature, but we have to beware a conversion could occur - * between the readings. The datasheet says we should either use - * the one-shot conversion register, which we don't want to do - * (disables hardware monitoring) or monitor the busy bit, which is - * impossible (we can't read the values and monitor that bit at the - * exact same time). So the solution used here is to read the high - * byte once, then the low byte, then the high byte again. If the new - * high byte matches the old one, then we have a valid reading. Else - * we have to read the low byte again, and now we believe we have a - * correct reading. - */ - if ((err = lm90_read_reg(client, regh, &oldh)) - || (err = lm90_read_reg(client, regl, &l)) - || (err = lm90_read_reg(client, regh, &newh))) - return err; - if (oldh != newh) { - err = lm90_read_reg(client, regl, &l); - if (err) - return err; - } - *value = (newh << 8) | l; - - return 0; -} - -/* - * client->update_lock must be held when calling this function (unless we are - * in detection or initialization steps), and while a remote channel other - * than channel 0 is selected. Also, calling code must make sure to re-select - * external channel 0 before releasing the lock. This is necessary because - * various registers have different meanings as a result of selecting a - * non-default remote channel. - */ -static inline void lm90_select_remote_channel(struct i2c_client *client, - struct lm90_data *data, - int channel) -{ - u8 config; - - if (data->kind == max6696) { - lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); - config &= ~0x08; - if (channel) - config |= 0x08; - i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, - config); - } -} - -/* - * Set conversion rate. - * client->update_lock must be held when calling this function (unless we are - * in detection or initialization steps). - */ -static void lm90_set_convrate(struct i2c_client *client, struct lm90_data *data, - unsigned int interval) -{ - int i; - unsigned int update_interval; - - /* Shift calculations to avoid rounding errors */ - interval <<= 6; - - /* find the nearest update rate */ - for (i = 0, update_interval = LM90_MAX_CONVRATE_MS << 6; - i < data->max_convrate; i++, update_interval >>= 1) - if (interval >= update_interval * 3 / 4) - break; - - i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, i); - data->update_interval = DIV_ROUND_CLOSEST(update_interval, 64); -} - -static struct lm90_data *lm90_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - unsigned long next_update; - - mutex_lock(&data->update_lock); - - next_update = data->last_updated - + msecs_to_jiffies(data->update_interval) + 1; - if (time_after(jiffies, next_update) || !data->valid) { - u8 h, l; - u8 alarms; - - dev_dbg(&client->dev, "Updating lm90 data.\n"); - lm90_read_reg(client, LM90_REG_R_LOCAL_LOW, &data->temp8[0]); - lm90_read_reg(client, LM90_REG_R_LOCAL_HIGH, &data->temp8[1]); - lm90_read_reg(client, LM90_REG_R_LOCAL_CRIT, &data->temp8[2]); - lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, &data->temp8[3]); - lm90_read_reg(client, LM90_REG_R_TCRIT_HYST, &data->temp_hyst); - - if (data->reg_local_ext) { - lm90_read16(client, LM90_REG_R_LOCAL_TEMP, - data->reg_local_ext, - &data->temp11[4]); - } else { - if (lm90_read_reg(client, LM90_REG_R_LOCAL_TEMP, - &h) == 0) - data->temp11[4] = h << 8; - } - lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, - LM90_REG_R_REMOTE_TEMPL, &data->temp11[0]); - - if (lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h) == 0) { - data->temp11[1] = h << 8; - if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) - && lm90_read_reg(client, LM90_REG_R_REMOTE_LOWL, - &l) == 0) - data->temp11[1] |= l; - } - if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h) == 0) { - data->temp11[2] = h << 8; - if ((data->flags & LM90_HAVE_REM_LIMIT_EXT) - && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, - &l) == 0) - data->temp11[2] |= l; - } - - if (data->flags & LM90_HAVE_OFFSET) { - if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH, - &h) == 0 - && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL, - &l) == 0) - data->temp11[3] = (h << 8) | l; - } - if (data->flags & LM90_HAVE_EMERGENCY) { - lm90_read_reg(client, MAX6659_REG_R_LOCAL_EMERG, - &data->temp8[4]); - lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, - &data->temp8[5]); - } - lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); - data->alarms = alarms; /* save as 16 bit value */ - - if (data->kind == max6696) { - lm90_select_remote_channel(client, data, 1); - lm90_read_reg(client, LM90_REG_R_REMOTE_CRIT, - &data->temp8[6]); - lm90_read_reg(client, MAX6659_REG_R_REMOTE_EMERG, - &data->temp8[7]); - lm90_read16(client, LM90_REG_R_REMOTE_TEMPH, - LM90_REG_R_REMOTE_TEMPL, &data->temp11[5]); - if (!lm90_read_reg(client, LM90_REG_R_REMOTE_LOWH, &h)) - data->temp11[6] = h << 8; - if (!lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &h)) - data->temp11[7] = h << 8; - lm90_select_remote_channel(client, data, 0); - - if (!lm90_read_reg(client, MAX6696_REG_R_STATUS2, - &alarms)) - data->alarms |= alarms << 8; - } - - /* - * Re-enable ALERT# output if it was originally enabled and - * relevant alarms are all clear - */ - if ((data->config_orig & 0x80) == 0 - && (data->alarms & data->alert_alarms) == 0) { - u8 config; - - lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); - if (config & 0x80) { - dev_dbg(&client->dev, "Re-enabling ALERT#\n"); - i2c_smbus_write_byte_data(client, - LM90_REG_W_CONFIG1, - config & ~0x80); - } - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Conversions - * For local temperatures and limits, critical limits and the hysteresis - * value, the LM90 uses signed 8-bit values with LSB = 1 degree Celsius. - * For remote temperatures and limits, it uses signed 11-bit values with - * LSB = 0.125 degree Celsius, left-justified in 16-bit registers. Some - * Maxim chips use unsigned values. - */ - -static inline int temp_from_s8(s8 val) -{ - return val * 1000; -} - -static inline int temp_from_u8(u8 val) -{ - return val * 1000; -} - -static inline int temp_from_s16(s16 val) -{ - return val / 32 * 125; -} - -static inline int temp_from_u16(u16 val) -{ - return val / 32 * 125; -} - -static s8 temp_to_s8(long val) -{ - if (val <= -128000) - return -128; - if (val >= 127000) - return 127; - if (val < 0) - return (val - 500) / 1000; - return (val + 500) / 1000; -} - -static u8 temp_to_u8(long val) -{ - if (val <= 0) - return 0; - if (val >= 255000) - return 255; - return (val + 500) / 1000; -} - -static s16 temp_to_s16(long val) -{ - if (val <= -128000) - return 0x8000; - if (val >= 127875) - return 0x7FE0; - if (val < 0) - return (val - 62) / 125 * 32; - return (val + 62) / 125 * 32; -} - -static u8 hyst_to_reg(long val) -{ - if (val <= 0) - return 0; - if (val >= 30500) - return 31; - return (val + 500) / 1000; -} - -/* - * ADT7461 in compatibility mode is almost identical to LM90 except that - * attempts to write values that are outside the range 0 < temp < 127 are - * treated as the boundary value. - * - * ADT7461 in "extended mode" operation uses unsigned integers offset by - * 64 (e.g., 0 -> -64 degC). The range is restricted to -64..191 degC. - */ -static inline int temp_from_u8_adt7461(struct lm90_data *data, u8 val) -{ - if (data->flags & LM90_FLAG_ADT7461_EXT) - return (val - 64) * 1000; - else - return temp_from_s8(val); -} - -static inline int temp_from_u16_adt7461(struct lm90_data *data, u16 val) -{ - if (data->flags & LM90_FLAG_ADT7461_EXT) - return (val - 0x4000) / 64 * 250; - else - return temp_from_s16(val); -} - -static u8 temp_to_u8_adt7461(struct lm90_data *data, long val) -{ - if (data->flags & LM90_FLAG_ADT7461_EXT) { - if (val <= -64000) - return 0; - if (val >= 191000) - return 0xFF; - return (val + 500 + 64000) / 1000; - } else { - if (val <= 0) - return 0; - if (val >= 127000) - return 127; - return (val + 500) / 1000; - } -} - -static u16 temp_to_u16_adt7461(struct lm90_data *data, long val) -{ - if (data->flags & LM90_FLAG_ADT7461_EXT) { - if (val <= -64000) - return 0; - if (val >= 191750) - return 0xFFC0; - return (val + 64000 + 125) / 250 * 64; - } else { - if (val <= 0) - return 0; - if (val >= 127750) - return 0x7FC0; - return (val + 125) / 250 * 64; - } -} - -/* - * Sysfs stuff - */ - -static ssize_t show_temp8(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm90_data *data = lm90_update_device(dev); - int temp; - - if (data->kind == adt7461) - temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); - else if (data->kind == max6646) - temp = temp_from_u8(data->temp8[attr->index]); - else - temp = temp_from_s8(data->temp8[attr->index]); - - /* +16 degrees offset for temp2 for the LM99 */ - if (data->kind == lm99 && attr->index == 3) - temp += 16000; - - return sprintf(buf, "%d\n", temp); -} - -static ssize_t set_temp8(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - static const u8 reg[8] = { - LM90_REG_W_LOCAL_LOW, - LM90_REG_W_LOCAL_HIGH, - LM90_REG_W_LOCAL_CRIT, - LM90_REG_W_REMOTE_CRIT, - MAX6659_REG_W_LOCAL_EMERG, - MAX6659_REG_W_REMOTE_EMERG, - LM90_REG_W_REMOTE_CRIT, - MAX6659_REG_W_REMOTE_EMERG, - }; - - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - /* +16 degrees offset for temp2 for the LM99 */ - if (data->kind == lm99 && attr->index == 3) - val -= 16000; - - mutex_lock(&data->update_lock); - if (data->kind == adt7461) - data->temp8[nr] = temp_to_u8_adt7461(data, val); - else if (data->kind == max6646) - data->temp8[nr] = temp_to_u8(val); - else - data->temp8[nr] = temp_to_s8(val); - - lm90_select_remote_channel(client, data, nr >= 6); - i2c_smbus_write_byte_data(client, reg[nr], data->temp8[nr]); - lm90_select_remote_channel(client, data, 0); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct lm90_data *data = lm90_update_device(dev); - int temp; - - if (data->kind == adt7461) - temp = temp_from_u16_adt7461(data, data->temp11[attr->index]); - else if (data->kind == max6646) - temp = temp_from_u16(data->temp11[attr->index]); - else - temp = temp_from_s16(data->temp11[attr->index]); - - /* +16 degrees offset for temp2 for the LM99 */ - if (data->kind == lm99 && attr->index <= 2) - temp += 16000; - - return sprintf(buf, "%d\n", temp); -} - -static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct { - u8 high; - u8 low; - int channel; - } reg[5] = { - { LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, 0 }, - { LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, 0 }, - { LM90_REG_W_REMOTE_OFFSH, LM90_REG_W_REMOTE_OFFSL, 0 }, - { LM90_REG_W_REMOTE_LOWH, LM90_REG_W_REMOTE_LOWL, 1 }, - { LM90_REG_W_REMOTE_HIGHH, LM90_REG_W_REMOTE_HIGHL, 1 } - }; - - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - int nr = attr->nr; - int index = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - /* +16 degrees offset for temp2 for the LM99 */ - if (data->kind == lm99 && index <= 2) - val -= 16000; - - mutex_lock(&data->update_lock); - if (data->kind == adt7461) - data->temp11[index] = temp_to_u16_adt7461(data, val); - else if (data->kind == max6646) - data->temp11[index] = temp_to_u8(val) << 8; - else if (data->flags & LM90_HAVE_REM_LIMIT_EXT) - data->temp11[index] = temp_to_s16(val); - else - data->temp11[index] = temp_to_s8(val) << 8; - - lm90_select_remote_channel(client, data, reg[nr].channel); - i2c_smbus_write_byte_data(client, reg[nr].high, - data->temp11[index] >> 8); - if (data->flags & LM90_HAVE_REM_LIMIT_EXT) - i2c_smbus_write_byte_data(client, reg[nr].low, - data->temp11[index] & 0xff); - lm90_select_remote_channel(client, data, 0); - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temphyst(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm90_data *data = lm90_update_device(dev); - int temp; - - if (data->kind == adt7461) - temp = temp_from_u8_adt7461(data, data->temp8[attr->index]); - else if (data->kind == max6646) - temp = temp_from_u8(data->temp8[attr->index]); - else - temp = temp_from_s8(data->temp8[attr->index]); - - /* +16 degrees offset for temp2 for the LM99 */ - if (data->kind == lm99 && attr->index == 3) - temp += 16000; - - return sprintf(buf, "%d\n", temp - temp_from_s8(data->temp_hyst)); -} - -static ssize_t set_temphyst(struct device *dev, struct device_attribute *dummy, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - long val; - int err; - int temp; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - mutex_lock(&data->update_lock); - if (data->kind == adt7461) - temp = temp_from_u8_adt7461(data, data->temp8[2]); - else if (data->kind == max6646) - temp = temp_from_u8(data->temp8[2]); - else - temp = temp_from_s8(data->temp8[2]); - - data->temp_hyst = hyst_to_reg(temp - val); - i2c_smbus_write_byte_data(client, LM90_REG_W_TCRIT_HYST, - data->temp_hyst); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, - char *buf) -{ - struct lm90_data *data = lm90_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct lm90_data *data = lm90_update_device(dev); - int bitnr = attr->index; - - return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); -} - -static ssize_t show_update_interval(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm90_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%u\n", data->update_interval); -} - -static ssize_t set_update_interval(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm90_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - lm90_set_convrate(client, data, SENSORS_LIMIT(val, 0, 100000)); - mutex_unlock(&data->update_lock); - - return count; -} - -static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp11, NULL, 0, 4); -static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp11, NULL, 0, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 0); -static SENSOR_DEVICE_ATTR_2(temp2_min, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 0, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 1); -static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 1, 2); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 2); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 3); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst, - set_temphyst, 2); -static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 3); -static SENSOR_DEVICE_ATTR_2(temp2_offset, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 2, 3); - -/* Individual alarm files */ -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -/* Raw alarm file for compatibility */ -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static DEVICE_ATTR(update_interval, S_IRUGO | S_IWUSR, show_update_interval, - set_update_interval); - -static struct attribute *lm90_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, - - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_update_interval.attr, - NULL -}; - -static const struct attribute_group lm90_group = { - .attrs = lm90_attributes, -}; - -/* - * Additional attributes for devices with emergency sensors - */ -static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 4); -static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 5); -static SENSOR_DEVICE_ATTR(temp1_emergency_hyst, S_IRUGO, show_temphyst, - NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_emergency_hyst, S_IRUGO, show_temphyst, - NULL, 5); - -static struct attribute *lm90_emergency_attributes[] = { - &sensor_dev_attr_temp1_emergency.dev_attr.attr, - &sensor_dev_attr_temp2_emergency.dev_attr.attr, - &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_emergency_hyst.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm90_emergency_group = { - .attrs = lm90_emergency_attributes, -}; - -static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 15); -static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 13); - -static struct attribute *lm90_emergency_alarm_attributes[] = { - &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm90_emergency_alarm_group = { - .attrs = lm90_emergency_alarm_attributes, -}; - -/* - * Additional attributes for devices with 3 temperature sensors - */ -static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp11, NULL, 0, 5); -static SENSOR_DEVICE_ATTR_2(temp3_min, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 3, 6); -static SENSOR_DEVICE_ATTR_2(temp3_max, S_IWUSR | S_IRUGO, show_temp11, - set_temp11, 4, 7); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 6); -static SENSOR_DEVICE_ATTR(temp3_crit_hyst, S_IRUGO, show_temphyst, NULL, 6); -static SENSOR_DEVICE_ATTR(temp3_emergency, S_IWUSR | S_IRUGO, show_temp8, - set_temp8, 7); -static SENSOR_DEVICE_ATTR(temp3_emergency_hyst, S_IRUGO, show_temphyst, - NULL, 7); - -static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(temp3_emergency_alarm, S_IRUGO, show_alarm, NULL, 14); - -static struct attribute *lm90_temp3_attributes[] = { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_emergency.dev_attr.attr, - &sensor_dev_attr_temp3_emergency_hyst.dev_attr.attr, - - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_emergency_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm90_temp3_group = { - .attrs = lm90_temp3_attributes, -}; - -/* pec used for ADM1032 only */ -static ssize_t show_pec(struct device *dev, struct device_attribute *dummy, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - return sprintf(buf, "%d\n", !!(client->flags & I2C_CLIENT_PEC)); -} - -static ssize_t set_pec(struct device *dev, struct device_attribute *dummy, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - switch (val) { - case 0: - client->flags &= ~I2C_CLIENT_PEC; - break; - case 1: - client->flags |= I2C_CLIENT_PEC; - break; - default: - return -EINVAL; - } - - return count; -} - -static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec); - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm90_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - const char *name = NULL; - int man_id, chip_id, config1, config2, convrate; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* detection and identification */ - man_id = i2c_smbus_read_byte_data(client, LM90_REG_R_MAN_ID); - chip_id = i2c_smbus_read_byte_data(client, LM90_REG_R_CHIP_ID); - config1 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG1); - convrate = i2c_smbus_read_byte_data(client, LM90_REG_R_CONVRATE); - if (man_id < 0 || chip_id < 0 || config1 < 0 || convrate < 0) - return -ENODEV; - - if (man_id == 0x01 || man_id == 0x5C || man_id == 0x41) { - config2 = i2c_smbus_read_byte_data(client, LM90_REG_R_CONFIG2); - if (config2 < 0) - return -ENODEV; - } else - config2 = 0; /* Make compiler happy */ - - if ((address == 0x4C || address == 0x4D) - && man_id == 0x01) { /* National Semiconductor */ - if ((config1 & 0x2A) == 0x00 - && (config2 & 0xF8) == 0x00 - && convrate <= 0x09) { - if (address == 0x4C - && (chip_id & 0xF0) == 0x20) { /* LM90 */ - name = "lm90"; - } else - if ((chip_id & 0xF0) == 0x30) { /* LM89/LM99 */ - name = "lm99"; - dev_info(&adapter->dev, - "Assuming LM99 chip at 0x%02x\n", - address); - dev_info(&adapter->dev, - "If it is an LM89, instantiate it " - "with the new_device sysfs " - "interface\n"); - } else - if (address == 0x4C - && (chip_id & 0xF0) == 0x10) { /* LM86 */ - name = "lm86"; - } - } - } else - if ((address == 0x4C || address == 0x4D) - && man_id == 0x41) { /* Analog Devices */ - if ((chip_id & 0xF0) == 0x40 /* ADM1032 */ - && (config1 & 0x3F) == 0x00 - && convrate <= 0x0A) { - name = "adm1032"; - /* - * The ADM1032 supports PEC, but only if combined - * transactions are not used. - */ - if (i2c_check_functionality(adapter, - I2C_FUNC_SMBUS_BYTE)) - info->flags |= I2C_CLIENT_PEC; - } else - if (chip_id == 0x51 /* ADT7461 */ - && (config1 & 0x1B) == 0x00 - && convrate <= 0x0A) { - name = "adt7461"; - } else - if (chip_id == 0x57 /* ADT7461A, NCT1008 */ - && (config1 & 0x1B) == 0x00 - && convrate <= 0x0A) { - name = "adt7461a"; - } - } else - if (man_id == 0x4D) { /* Maxim */ - int emerg, emerg2, status2; - - /* - * We read MAX6659_REG_R_REMOTE_EMERG twice, and re-read - * LM90_REG_R_MAN_ID in between. If MAX6659_REG_R_REMOTE_EMERG - * exists, both readings will reflect the same value. Otherwise, - * the readings will be different. - */ - emerg = i2c_smbus_read_byte_data(client, - MAX6659_REG_R_REMOTE_EMERG); - man_id = i2c_smbus_read_byte_data(client, - LM90_REG_R_MAN_ID); - emerg2 = i2c_smbus_read_byte_data(client, - MAX6659_REG_R_REMOTE_EMERG); - status2 = i2c_smbus_read_byte_data(client, - MAX6696_REG_R_STATUS2); - if (emerg < 0 || man_id < 0 || emerg2 < 0 || status2 < 0) - return -ENODEV; - - /* - * The MAX6657, MAX6658 and MAX6659 do NOT have a chip_id - * register. Reading from that address will return the last - * read value, which in our case is those of the man_id - * register. Likewise, the config1 register seems to lack a - * low nibble, so the value will be those of the previous - * read, so in our case those of the man_id register. - * MAX6659 has a third set of upper temperature limit registers. - * Those registers also return values on MAX6657 and MAX6658, - * thus the only way to detect MAX6659 is by its address. - * For this reason it will be mis-detected as MAX6657 if its - * address is 0x4C. - */ - if (chip_id == man_id - && (address == 0x4C || address == 0x4D || address == 0x4E) - && (config1 & 0x1F) == (man_id & 0x0F) - && convrate <= 0x09) { - if (address == 0x4C) - name = "max6657"; - else - name = "max6659"; - } else - /* - * Even though MAX6695 and MAX6696 do not have a chip ID - * register, reading it returns 0x01. Bit 4 of the config1 - * register is unused and should return zero when read. Bit 0 of - * the status2 register is unused and should return zero when - * read. - * - * MAX6695 and MAX6696 have an additional set of temperature - * limit registers. We can detect those chips by checking if - * one of those registers exists. - */ - if (chip_id == 0x01 - && (config1 & 0x10) == 0x00 - && (status2 & 0x01) == 0x00 - && emerg == emerg2 - && convrate <= 0x07) { - name = "max6696"; - } else - /* - * The chip_id register of the MAX6680 and MAX6681 holds the - * revision of the chip. The lowest bit of the config1 register - * is unused and should return zero when read, so should the - * second to last bit of config1 (software reset). - */ - if (chip_id == 0x01 - && (config1 & 0x03) == 0x00 - && convrate <= 0x07) { - name = "max6680"; - } else - /* - * The chip_id register of the MAX6646/6647/6649 holds the - * revision of the chip. The lowest 6 bits of the config1 - * register are unused and should return zero when read. - */ - if (chip_id == 0x59 - && (config1 & 0x3f) == 0x00 - && convrate <= 0x07) { - name = "max6646"; - } - } else - if (address == 0x4C - && man_id == 0x5C) { /* Winbond/Nuvoton */ - if ((config1 & 0x2A) == 0x00 - && (config2 & 0xF8) == 0x00) { - if (chip_id == 0x01 /* W83L771W/G */ - && convrate <= 0x09) { - name = "w83l771"; - } else - if ((chip_id & 0xFE) == 0x10 /* W83L771AWG/ASG */ - && convrate <= 0x08) { - name = "w83l771"; - } - } - } else - if (address >= 0x48 && address <= 0x4F - && man_id == 0xA1) { /* NXP Semiconductor/Philips */ - if (chip_id == 0x00 - && (config1 & 0x2A) == 0x00 - && (config2 & 0xFE) == 0x00 - && convrate <= 0x09) { - name = "sa56004"; - } - } else - if ((address == 0x4C || address == 0x4D) - && man_id == 0x47) { /* GMT */ - if (chip_id == 0x01 /* G781 */ - && (config1 & 0x3F) == 0x00 - && convrate <= 0x08) - name = "g781"; - } - - if (!name) { /* identification failed */ - dev_dbg(&adapter->dev, - "Unsupported chip at 0x%02x (man_id=0x%02X, " - "chip_id=0x%02X)\n", address, man_id, chip_id); - return -ENODEV; - } - - strlcpy(info->type, name, I2C_NAME_SIZE); - - return 0; -} - -static void lm90_remove_files(struct i2c_client *client, struct lm90_data *data) -{ - struct device *dev = &client->dev; - - if (data->flags & LM90_HAVE_TEMP3) - sysfs_remove_group(&dev->kobj, &lm90_temp3_group); - if (data->flags & LM90_HAVE_EMERGENCY_ALARM) - sysfs_remove_group(&dev->kobj, &lm90_emergency_alarm_group); - if (data->flags & LM90_HAVE_EMERGENCY) - sysfs_remove_group(&dev->kobj, &lm90_emergency_group); - if (data->flags & LM90_HAVE_OFFSET) - device_remove_file(dev, &sensor_dev_attr_temp2_offset.dev_attr); - device_remove_file(dev, &dev_attr_pec); - sysfs_remove_group(&dev->kobj, &lm90_group); -} - -static void lm90_restore_conf(struct i2c_client *client, struct lm90_data *data) -{ - /* Restore initial configuration */ - i2c_smbus_write_byte_data(client, LM90_REG_W_CONVRATE, - data->convrate_orig); - i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, - data->config_orig); -} - -static void lm90_init_client(struct i2c_client *client) -{ - u8 config, convrate; - struct lm90_data *data = i2c_get_clientdata(client); - - if (lm90_read_reg(client, LM90_REG_R_CONVRATE, &convrate) < 0) { - dev_warn(&client->dev, "Failed to read convrate register!\n"); - convrate = LM90_DEF_CONVRATE_RVAL; - } - data->convrate_orig = convrate; - - /* - * Start the conversions. - */ - lm90_set_convrate(client, data, 500); /* 500ms; 2Hz conversion rate */ - if (lm90_read_reg(client, LM90_REG_R_CONFIG1, &config) < 0) { - dev_warn(&client->dev, "Initialization failed!\n"); - return; - } - data->config_orig = config; - - /* Check Temperature Range Select */ - if (data->kind == adt7461) { - if (config & 0x04) - data->flags |= LM90_FLAG_ADT7461_EXT; - } - - /* - * Put MAX6680/MAX8881 into extended resolution (bit 0x10, - * 0.125 degree resolution) and range (0x08, extend range - * to -64 degree) mode for the remote temperature sensor. - */ - if (data->kind == max6680) - config |= 0x18; - - /* - * Select external channel 0 for max6695/96 - */ - if (data->kind == max6696) - config &= ~0x08; - - config &= 0xBF; /* run */ - if (config != data->config_orig) /* Only write if changed */ - i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config); -} - -static int lm90_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - struct i2c_adapter *adapter = to_i2c_adapter(dev->parent); - struct lm90_data *data; - int err; - - data = kzalloc(sizeof(struct lm90_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Set the device type */ - data->kind = id->driver_data; - if (data->kind == adm1032) { - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) - client->flags &= ~I2C_CLIENT_PEC; - } - - /* - * Different devices have different alarm bits triggering the - * ALERT# output - */ - data->alert_alarms = lm90_params[data->kind].alert_alarms; - - /* Set chip capabilities */ - data->flags = lm90_params[data->kind].flags; - data->reg_local_ext = lm90_params[data->kind].reg_local_ext; - - /* Set maximum conversion rate */ - data->max_convrate = lm90_params[data->kind].max_convrate; - - /* Initialize the LM90 chip */ - lm90_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&dev->kobj, &lm90_group); - if (err) - goto exit_restore; - if (client->flags & I2C_CLIENT_PEC) { - err = device_create_file(dev, &dev_attr_pec); - if (err) - goto exit_remove_files; - } - if (data->flags & LM90_HAVE_OFFSET) { - err = device_create_file(dev, - &sensor_dev_attr_temp2_offset.dev_attr); - if (err) - goto exit_remove_files; - } - if (data->flags & LM90_HAVE_EMERGENCY) { - err = sysfs_create_group(&dev->kobj, &lm90_emergency_group); - if (err) - goto exit_remove_files; - } - if (data->flags & LM90_HAVE_EMERGENCY_ALARM) { - err = sysfs_create_group(&dev->kobj, - &lm90_emergency_alarm_group); - if (err) - goto exit_remove_files; - } - if (data->flags & LM90_HAVE_TEMP3) { - err = sysfs_create_group(&dev->kobj, &lm90_temp3_group); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - lm90_remove_files(client, data); -exit_restore: - lm90_restore_conf(client, data); - kfree(data); -exit: - return err; -} - -static int lm90_remove(struct i2c_client *client) -{ - struct lm90_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - lm90_remove_files(client, data); - lm90_restore_conf(client, data); - - kfree(data); - return 0; -} - -static void lm90_alert(struct i2c_client *client, unsigned int flag) -{ - struct lm90_data *data = i2c_get_clientdata(client); - u8 config, alarms, alarms2 = 0; - - lm90_read_reg(client, LM90_REG_R_STATUS, &alarms); - - if (data->kind == max6696) - lm90_read_reg(client, MAX6696_REG_R_STATUS2, &alarms2); - - if ((alarms & 0x7f) == 0 && (alarms2 & 0xfe) == 0) { - dev_info(&client->dev, "Everything OK\n"); - } else { - if (alarms & 0x61) - dev_warn(&client->dev, - "temp%d out of range, please check!\n", 1); - if (alarms & 0x1a) - dev_warn(&client->dev, - "temp%d out of range, please check!\n", 2); - if (alarms & 0x04) - dev_warn(&client->dev, - "temp%d diode open, please check!\n", 2); - - if (alarms2 & 0x18) - dev_warn(&client->dev, - "temp%d out of range, please check!\n", 3); - - /* - * Disable ALERT# output, because these chips don't implement - * SMBus alert correctly; they should only hold the alert line - * low briefly. - */ - if ((data->flags & LM90_HAVE_BROKEN_ALERT) - && (alarms & data->alert_alarms)) { - dev_dbg(&client->dev, "Disabling ALERT#\n"); - lm90_read_reg(client, LM90_REG_R_CONFIG1, &config); - i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, - config | 0x80); - } - } -} - -static struct i2c_driver lm90_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm90", - }, - .probe = lm90_probe, - .remove = lm90_remove, - .alert = lm90_alert, - .id_table = lm90_id, - .detect = lm90_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm90_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("LM90/ADM1032 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm92.c b/ANDROID_3.4.5/drivers/hwmon/lm92.c deleted file mode 100644 index fdc691a4..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm92.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * lm92 - Hardware monitoring driver - * Copyright (C) 2005-2008 Jean Delvare - * - * Based on the lm90 driver, with some ideas taken from the lm_sensors - * lm92 driver as well. - * - * The LM92 is a sensor chip made by National Semiconductor. It reports - * its own temperature with a 0.0625 deg resolution and a 0.33 deg - * accuracy. Complete datasheet can be obtained from National's website - * at: - * http://www.national.com/pf/LM/LM92.html - * - * This driver also supports the MAX6635 sensor chip made by Maxim. - * This chip is compatible with the LM92, but has a lesser accuracy - * (1.0 deg). Complete datasheet can be obtained from Maxim's website - * at: - * http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3074 - * - * Since the LM92 was the first chipset supported by this driver, most - * comments will refer to this chipset, but are actually general and - * concern all supported chipsets, unless mentioned otherwise. - * - * Support could easily be added for the National Semiconductor LM76 - * and Maxim MAX6633 and MAX6634 chips, which are mostly compatible - * with the LM92. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * The LM92 and MAX6635 have 2 two-state pins for address selection, - * resulting in 4 possible addresses. - */ -static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, - I2C_CLIENT_END }; - -/* The LM92 registers */ -#define LM92_REG_CONFIG 0x01 /* 8-bit, RW */ -#define LM92_REG_TEMP 0x00 /* 16-bit, RO */ -#define LM92_REG_TEMP_HYST 0x02 /* 16-bit, RW */ -#define LM92_REG_TEMP_CRIT 0x03 /* 16-bit, RW */ -#define LM92_REG_TEMP_LOW 0x04 /* 16-bit, RW */ -#define LM92_REG_TEMP_HIGH 0x05 /* 16-bit, RW */ -#define LM92_REG_MAN_ID 0x07 /* 16-bit, RO, LM92 only */ - -/* - * The LM92 uses signed 13-bit values with LSB = 0.0625 degree Celsius, - * left-justified in 16-bit registers. No rounding is done, with such - * a resolution it's just not worth it. Note that the MAX6635 doesn't - * make use of the 4 lower bits for limits (i.e. effective resolution - * for limits is 1 degree Celsius). - */ -static inline int TEMP_FROM_REG(s16 reg) -{ - return reg / 8 * 625 / 10; -} - -static inline s16 TEMP_TO_REG(int val) -{ - if (val <= -60000) - return -60000 * 10 / 625 * 8; - if (val >= 160000) - return 160000 * 10 / 625 * 8; - return val * 10 / 625 * 8; -} - -/* Alarm flags are stored in the 3 LSB of the temperature register */ -static inline u8 ALARMS_FROM_REG(s16 reg) -{ - return reg & 0x0007; -} - -/* Driver data (common to all clients) */ -static struct i2c_driver lm92_driver; - -/* Client data (each client gets its own) */ -struct lm92_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - s16 temp1_input, temp1_crit, temp1_min, temp1_max, temp1_hyst; -}; - - -/* - * Sysfs attributes and callback functions - */ - -static struct lm92_data *lm92_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm92_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) - || !data->valid) { - dev_dbg(&client->dev, "Updating lm92 data\n"); - data->temp1_input = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP); - data->temp1_hyst = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_HYST); - data->temp1_crit = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_CRIT); - data->temp1_min = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_LOW); - data->temp1_max = i2c_smbus_read_word_swapped(client, - LM92_REG_TEMP_HIGH); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -#define show_temp(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct lm92_data *data = lm92_update_device(dev); \ - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value)); \ -} -show_temp(temp1_input); -show_temp(temp1_crit); -show_temp(temp1_min); -show_temp(temp1_max); - -#define set_temp(value, reg) \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, \ - const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct lm92_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ -\ - mutex_lock(&data->update_lock); \ - data->value = TEMP_TO_REG(val); \ - i2c_smbus_write_word_swapped(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} -set_temp(temp1_crit, LM92_REG_TEMP_CRIT); -set_temp(temp1_min, LM92_REG_TEMP_LOW); -set_temp(temp1_max, LM92_REG_TEMP_HIGH); - -static ssize_t show_temp1_crit_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_crit) - - TEMP_FROM_REG(data->temp1_hyst)); -} -static ssize_t show_temp1_max_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_max) - - TEMP_FROM_REG(data->temp1_hyst)); -} -static ssize_t show_temp1_min_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp1_min) - + TEMP_FROM_REG(data->temp1_hyst)); -} - -static ssize_t set_temp1_crit_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm92_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp1_hyst = TEMP_FROM_REG(data->temp1_crit) - val; - i2c_smbus_write_word_swapped(client, LM92_REG_TEMP_HYST, - TEMP_TO_REG(data->temp1_hyst)); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->temp1_input)); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct lm92_data *data = lm92_update_device(dev); - return sprintf(buf, "%d\n", (data->temp1_input >> bitnr) & 1); -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp1_input, NULL); -static DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp1_crit, - set_temp1_crit); -static DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp1_crit_hyst, - set_temp1_crit_hyst); -static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp1_min, - set_temp1_min); -static DEVICE_ATTR(temp1_min_hyst, S_IRUGO, show_temp1_min_hyst, NULL); -static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp1_max, - set_temp1_max); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO, show_temp1_max_hyst, NULL); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 1); - - -/* - * Detection and registration - */ - -static void lm92_init_client(struct i2c_client *client) -{ - u8 config; - - /* Start the conversions if needed */ - config = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG); - if (config & 0x01) - i2c_smbus_write_byte_data(client, LM92_REG_CONFIG, - config & 0xFE); -} - -/* - * The MAX6635 has no identification register, so we have to use tricks - * to identify it reliably. This is somewhat slow. - * Note that we do NOT rely on the 2 MSB of the configuration register - * always reading 0, as suggested by the datasheet, because it was once - * reported not to be true. - */ -static int max6635_check(struct i2c_client *client) -{ - u16 temp_low, temp_high, temp_hyst, temp_crit; - u8 conf; - int i; - - /* - * No manufacturer ID register, so a read from this address will - * always return the last read value. - */ - temp_low = i2c_smbus_read_word_data(client, LM92_REG_TEMP_LOW); - if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_low) - return 0; - temp_high = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HIGH); - if (i2c_smbus_read_word_data(client, LM92_REG_MAN_ID) != temp_high) - return 0; - - /* Limits are stored as integer values (signed, 9-bit). */ - if ((temp_low & 0x7f00) || (temp_high & 0x7f00)) - return 0; - temp_hyst = i2c_smbus_read_word_data(client, LM92_REG_TEMP_HYST); - temp_crit = i2c_smbus_read_word_data(client, LM92_REG_TEMP_CRIT); - if ((temp_hyst & 0x7f00) || (temp_crit & 0x7f00)) - return 0; - - /* - * Registers addresses were found to cycle over 16-byte boundaries. - * We don't test all registers with all offsets so as to save some - * reads and time, but this should still be sufficient to dismiss - * non-MAX6635 chips. - */ - conf = i2c_smbus_read_byte_data(client, LM92_REG_CONFIG); - for (i = 16; i < 96; i *= 2) { - if (temp_hyst != i2c_smbus_read_word_data(client, - LM92_REG_TEMP_HYST + i - 16) - || temp_crit != i2c_smbus_read_word_data(client, - LM92_REG_TEMP_CRIT + i) - || temp_low != i2c_smbus_read_word_data(client, - LM92_REG_TEMP_LOW + i + 16) - || temp_high != i2c_smbus_read_word_data(client, - LM92_REG_TEMP_HIGH + i + 32) - || conf != i2c_smbus_read_byte_data(client, - LM92_REG_CONFIG + i)) - return 0; - } - - return 1; -} - -static struct attribute *lm92_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_crit.attr, - &dev_attr_temp1_crit_hyst.attr, - &dev_attr_temp1_min.attr, - &dev_attr_temp1_min_hyst.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &dev_attr_alarms.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group lm92_group = { - .attrs = lm92_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm92_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - u8 config; - u16 man_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - config = i2c_smbus_read_byte_data(new_client, LM92_REG_CONFIG); - man_id = i2c_smbus_read_word_data(new_client, LM92_REG_MAN_ID); - - if ((config & 0xe0) == 0x00 && man_id == 0x0180) - pr_info("lm92: Found National Semiconductor LM92 chip\n"); - else if (max6635_check(new_client)) - pr_info("lm92: Found Maxim MAX6635 chip\n"); - else - return -ENODEV; - - strlcpy(info->type, "lm92", I2C_NAME_SIZE); - - return 0; -} - -static int lm92_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm92_data *data; - int err; - - data = kzalloc(sizeof(struct lm92_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Initialize the chipset */ - lm92_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &lm92_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &lm92_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int lm92_remove(struct i2c_client *client) -{ - struct lm92_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm92_group); - - kfree(data); - return 0; -} - - -/* - * Module and driver stuff - */ - -static const struct i2c_device_id lm92_id[] = { - { "lm92", 0 }, - /* max6635 could be added here */ - { } -}; -MODULE_DEVICE_TABLE(i2c, lm92_id); - -static struct i2c_driver lm92_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm92", - }, - .probe = lm92_probe, - .remove = lm92_remove, - .id_table = lm92_id, - .detect = lm92_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm92_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("LM92/MAX6635 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm93.c b/ANDROID_3.4.5/drivers/hwmon/lm93.c deleted file mode 100644 index 67e8fe25..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm93.c +++ /dev/null @@ -1,2814 +0,0 @@ -/* - * lm93.c - Part of lm_sensors, Linux kernel modules for hardware monitoring - * - * Author/Maintainer: Mark M. Hoffman - * Copyright (c) 2004 Utilitek Systems, Inc. - * - * derived in part from lm78.c: - * Copyright (c) 1998, 1999 Frodo Looijaard - * - * derived in part from lm85.c: - * Copyright (c) 2002, 2003 Philip Pokorny - * Copyright (c) 2003 Margit Schubert-While - * - * derived in part from w83l785ts.c: - * Copyright (c) 2003-2004 Jean Delvare - * - * Ported to Linux 2.6 by Eric J. Bowersox - * Copyright (c) 2005 Aspen Systems, Inc. - * - * Adapted to 2.6.20 by Carsten Emde - * Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab - * - * Modified for mainline integration by Hans J. Koch - * Copyright (c) 2007 Hans J. Koch, Linutronix GmbH - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* LM93 REGISTER ADDRESSES */ - -/* miscellaneous */ -#define LM93_REG_MFR_ID 0x3e -#define LM93_REG_VER 0x3f -#define LM93_REG_STATUS_CONTROL 0xe2 -#define LM93_REG_CONFIG 0xe3 -#define LM93_REG_SLEEP_CONTROL 0xe4 - -/* alarm values start here */ -#define LM93_REG_HOST_ERROR_1 0x48 - -/* voltage inputs: in1-in16 (nr => 0-15) */ -#define LM93_REG_IN(nr) (0x56 + (nr)) -#define LM93_REG_IN_MIN(nr) (0x90 + (nr) * 2) -#define LM93_REG_IN_MAX(nr) (0x91 + (nr) * 2) - -/* temperature inputs: temp1-temp4 (nr => 0-3) */ -#define LM93_REG_TEMP(nr) (0x50 + (nr)) -#define LM93_REG_TEMP_MIN(nr) (0x78 + (nr) * 2) -#define LM93_REG_TEMP_MAX(nr) (0x79 + (nr) * 2) - -/* temp[1-4]_auto_boost (nr => 0-3) */ -#define LM93_REG_BOOST(nr) (0x80 + (nr)) - -/* #PROCHOT inputs: prochot1-prochot2 (nr => 0-1) */ -#define LM93_REG_PROCHOT_CUR(nr) (0x67 + (nr) * 2) -#define LM93_REG_PROCHOT_AVG(nr) (0x68 + (nr) * 2) -#define LM93_REG_PROCHOT_MAX(nr) (0xb0 + (nr)) - -/* fan tach inputs: fan1-fan4 (nr => 0-3) */ -#define LM93_REG_FAN(nr) (0x6e + (nr) * 2) -#define LM93_REG_FAN_MIN(nr) (0xb4 + (nr) * 2) - -/* pwm outputs: pwm1-pwm2 (nr => 0-1, reg => 0-3) */ -#define LM93_REG_PWM_CTL(nr, reg) (0xc8 + (reg) + (nr) * 4) -#define LM93_PWM_CTL1 0x0 -#define LM93_PWM_CTL2 0x1 -#define LM93_PWM_CTL3 0x2 -#define LM93_PWM_CTL4 0x3 - -/* GPIO input state */ -#define LM93_REG_GPI 0x6b - -/* vid inputs: vid1-vid2 (nr => 0-1) */ -#define LM93_REG_VID(nr) (0x6c + (nr)) - -/* vccp1 & vccp2: VID relative inputs (nr => 0-1) */ -#define LM93_REG_VCCP_LIMIT_OFF(nr) (0xb2 + (nr)) - -/* temp[1-4]_auto_boost_hyst */ -#define LM93_REG_BOOST_HYST_12 0xc0 -#define LM93_REG_BOOST_HYST_34 0xc1 -#define LM93_REG_BOOST_HYST(nr) (0xc0 + (nr)/2) - -/* temp[1-4]_auto_pwm_[min|hyst] */ -#define LM93_REG_PWM_MIN_HYST_12 0xc3 -#define LM93_REG_PWM_MIN_HYST_34 0xc4 -#define LM93_REG_PWM_MIN_HYST(nr) (0xc3 + (nr)/2) - -/* prochot_override & prochot_interval */ -#define LM93_REG_PROCHOT_OVERRIDE 0xc6 -#define LM93_REG_PROCHOT_INTERVAL 0xc7 - -/* temp[1-4]_auto_base (nr => 0-3) */ -#define LM93_REG_TEMP_BASE(nr) (0xd0 + (nr)) - -/* temp[1-4]_auto_offsets (step => 0-11) */ -#define LM93_REG_TEMP_OFFSET(step) (0xd4 + (step)) - -/* #PROCHOT & #VRDHOT PWM ramp control */ -#define LM93_REG_PWM_RAMP_CTL 0xbf - -/* miscellaneous */ -#define LM93_REG_SFC1 0xbc -#define LM93_REG_SFC2 0xbd -#define LM93_REG_GPI_VID_CTL 0xbe -#define LM93_REG_SF_TACH_TO_PWM 0xe0 - -/* error masks */ -#define LM93_REG_GPI_ERR_MASK 0xec -#define LM93_REG_MISC_ERR_MASK 0xed - -/* LM93 REGISTER VALUES */ -#define LM93_MFR_ID 0x73 -#define LM93_MFR_ID_PROTOTYPE 0x72 - -/* LM94 REGISTER VALUES */ -#define LM94_MFR_ID_2 0x7a -#define LM94_MFR_ID 0x79 -#define LM94_MFR_ID_PROTOTYPE 0x78 - -/* SMBus capabilities */ -#define LM93_SMBUS_FUNC_FULL (I2C_FUNC_SMBUS_BYTE_DATA | \ - I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA) -#define LM93_SMBUS_FUNC_MIN (I2C_FUNC_SMBUS_BYTE_DATA | \ - I2C_FUNC_SMBUS_WORD_DATA) - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -/* Insmod parameters */ - -static bool disable_block; -module_param(disable_block, bool, 0); -MODULE_PARM_DESC(disable_block, - "Set to non-zero to disable SMBus block data transactions."); - -static bool init; -module_param(init, bool, 0); -MODULE_PARM_DESC(init, "Set to non-zero to force chip initialization."); - -static int vccp_limit_type[2] = {0, 0}; -module_param_array(vccp_limit_type, int, NULL, 0); -MODULE_PARM_DESC(vccp_limit_type, "Configures in7 and in8 limit modes."); - -static int vid_agtl; -module_param(vid_agtl, int, 0); -MODULE_PARM_DESC(vid_agtl, "Configures VID pin input thresholds."); - -/* Driver data */ -static struct i2c_driver lm93_driver; - -/* LM93 BLOCK READ COMMANDS */ -static const struct { u8 cmd; u8 len; } lm93_block_read_cmds[12] = { - { 0xf2, 8 }, - { 0xf3, 8 }, - { 0xf4, 6 }, - { 0xf5, 16 }, - { 0xf6, 4 }, - { 0xf7, 8 }, - { 0xf8, 12 }, - { 0xf9, 32 }, - { 0xfa, 8 }, - { 0xfb, 8 }, - { 0xfc, 16 }, - { 0xfd, 9 }, -}; - -/* - * ALARMS: SYSCTL format described further below - * REG: 64 bits in 8 registers, as immediately below - */ -struct block1_t { - u8 host_status_1; - u8 host_status_2; - u8 host_status_3; - u8 host_status_4; - u8 p1_prochot_status; - u8 p2_prochot_status; - u8 gpi_status; - u8 fan_status; -}; - -/* - * Client-specific data - */ -struct lm93_data { - struct device *hwmon_dev; - - struct mutex update_lock; - unsigned long last_updated; /* In jiffies */ - - /* client update function */ - void (*update)(struct lm93_data *, struct i2c_client *); - - char valid; /* !=0 if following fields are valid */ - - /* register values, arranged by block read groups */ - struct block1_t block1; - - /* - * temp1 - temp4: unfiltered readings - * temp1 - temp2: filtered readings - */ - u8 block2[6]; - - /* vin1 - vin16: readings */ - u8 block3[16]; - - /* prochot1 - prochot2: readings */ - struct { - u8 cur; - u8 avg; - } block4[2]; - - /* fan counts 1-4 => 14-bits, LE, *left* justified */ - u16 block5[4]; - - /* block6 has a lot of data we don't need */ - struct { - u8 min; - u8 max; - } temp_lim[4]; - - /* vin1 - vin16: low and high limits */ - struct { - u8 min; - u8 max; - } block7[16]; - - /* fan count limits 1-4 => same format as block5 */ - u16 block8[4]; - - /* pwm control registers (2 pwms, 4 regs) */ - u8 block9[2][4]; - - /* auto/pwm base temp and offset temp registers */ - struct { - u8 base[4]; - u8 offset[12]; - } block10; - - /* master config register */ - u8 config; - - /* VID1 & VID2 => register format, 6-bits, right justified */ - u8 vid[2]; - - /* prochot1 - prochot2: limits */ - u8 prochot_max[2]; - - /* vccp1 & vccp2 (in7 & in8): VID relative limits (register format) */ - u8 vccp_limits[2]; - - /* GPIO input state (register format, i.e. inverted) */ - u8 gpi; - - /* #PROCHOT override (register format) */ - u8 prochot_override; - - /* #PROCHOT intervals (register format) */ - u8 prochot_interval; - - /* Fan Boost Temperatures (register format) */ - u8 boost[4]; - - /* Fan Boost Hysteresis (register format) */ - u8 boost_hyst[2]; - - /* Temperature Zone Min. PWM & Hysteresis (register format) */ - u8 auto_pwm_min_hyst[2]; - - /* #PROCHOT & #VRDHOT PWM Ramp Control */ - u8 pwm_ramp_ctl; - - /* miscellaneous setup regs */ - u8 sfc1; - u8 sfc2; - u8 sf_tach_to_pwm; - - /* - * The two PWM CTL2 registers can read something other than what was - * last written for the OVR_DC field (duty cycle override). So, we - * save the user-commanded value here. - */ - u8 pwm_override[2]; -}; - -/* - * VID: mV - * REG: 6-bits, right justified, *always* using Intel VRM/VRD 10 - */ -static int LM93_VID_FROM_REG(u8 reg) -{ - return vid_from_reg((reg & 0x3f), 100); -} - -/* min, max, and nominal register values, per channel (u8) */ -static const u8 lm93_vin_reg_min[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae, -}; -static const u8 lm93_vin_reg_max[16] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd1, -}; -/* - * Values from the datasheet. They're here for documentation only. - * static const u8 lm93_vin_reg_nom[16] = { - * 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, - * 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0xc0, - * }; - */ - -/* min, max, and nominal voltage readings, per channel (mV)*/ -static const unsigned long lm93_vin_val_min[16] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 3000, -}; - -static const unsigned long lm93_vin_val_max[16] = { - 1236, 1236, 1236, 1600, 2000, 2000, 1600, 1600, - 4400, 6500, 3333, 2625, 1312, 1312, 1236, 3600, -}; -/* - * Values from the datasheet. They're here for documentation only. - * static const unsigned long lm93_vin_val_nom[16] = { - * 927, 927, 927, 1200, 1500, 1500, 1200, 1200, - * 3300, 5000, 2500, 1969, 984, 984, 309, 3300, - * }; - */ - -static unsigned LM93_IN_FROM_REG(int nr, u8 reg) -{ - const long uV_max = lm93_vin_val_max[nr] * 1000; - const long uV_min = lm93_vin_val_min[nr] * 1000; - - const long slope = (uV_max - uV_min) / - (lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]); - const long intercept = uV_min - slope * lm93_vin_reg_min[nr]; - - return (slope * reg + intercept + 500) / 1000; -} - -/* - * IN: mV, limits determined by channel nr - * REG: scaling determined by channel nr - */ -static u8 LM93_IN_TO_REG(int nr, unsigned val) -{ - /* range limit */ - const long mV = SENSORS_LIMIT(val, - lm93_vin_val_min[nr], lm93_vin_val_max[nr]); - - /* try not to lose too much precision here */ - const long uV = mV * 1000; - const long uV_max = lm93_vin_val_max[nr] * 1000; - const long uV_min = lm93_vin_val_min[nr] * 1000; - - /* convert */ - const long slope = (uV_max - uV_min) / - (lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]); - const long intercept = uV_min - slope * lm93_vin_reg_min[nr]; - - u8 result = ((uV - intercept + (slope/2)) / slope); - result = SENSORS_LIMIT(result, - lm93_vin_reg_min[nr], lm93_vin_reg_max[nr]); - return result; -} - -/* vid in mV, upper == 0 indicates low limit, otherwise upper limit */ -static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid) -{ - const long uV_offset = upper ? (((reg >> 4 & 0x0f) + 1) * 12500) : - (((reg >> 0 & 0x0f) + 1) * -25000); - const long uV_vid = vid * 1000; - return (uV_vid + uV_offset + 5000) / 10000; -} - -#define LM93_IN_MIN_FROM_REG(reg, vid) LM93_IN_REL_FROM_REG((reg), 0, (vid)) -#define LM93_IN_MAX_FROM_REG(reg, vid) LM93_IN_REL_FROM_REG((reg), 1, (vid)) - -/* - * vid in mV , upper == 0 indicates low limit, otherwise upper limit - * upper also determines which nibble of the register is returned - * (the other nibble will be 0x0) - */ -static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid) -{ - long uV_offset = vid * 1000 - val * 10000; - if (upper) { - uV_offset = SENSORS_LIMIT(uV_offset, 12500, 200000); - return (u8)((uV_offset / 12500 - 1) << 4); - } else { - uV_offset = SENSORS_LIMIT(uV_offset, -400000, -25000); - return (u8)((uV_offset / -25000 - 1) << 0); - } -} - -/* - * TEMP: 1/1000 degrees C (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static int LM93_TEMP_FROM_REG(u8 reg) -{ - return (s8)reg * 1000; -} - -#define LM93_TEMP_MIN (-128000) -#define LM93_TEMP_MAX (127000) - -/* - * TEMP: 1/1000 degrees C (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static u8 LM93_TEMP_TO_REG(long temp) -{ - int ntemp = SENSORS_LIMIT(temp, LM93_TEMP_MIN, LM93_TEMP_MAX); - ntemp += (ntemp < 0 ? -500 : 500); - return (u8)(ntemp / 1000); -} - -/* Determine 4-bit temperature offset resolution */ -static int LM93_TEMP_OFFSET_MODE_FROM_REG(u8 sfc2, int nr) -{ - /* mode: 0 => 1C/bit, nonzero => 0.5C/bit */ - return sfc2 & (nr < 2 ? 0x10 : 0x20); -} - -/* - * This function is common to all 4-bit temperature offsets - * reg is 4 bits right justified - * mode 0 => 1C/bit, mode !0 => 0.5C/bit - */ -static int LM93_TEMP_OFFSET_FROM_REG(u8 reg, int mode) -{ - return (reg & 0x0f) * (mode ? 5 : 10); -} - -#define LM93_TEMP_OFFSET_MIN (0) -#define LM93_TEMP_OFFSET_MAX0 (150) -#define LM93_TEMP_OFFSET_MAX1 (75) - -/* - * This function is common to all 4-bit temperature offsets - * returns 4 bits right justified - * mode 0 => 1C/bit, mode !0 => 0.5C/bit - */ -static u8 LM93_TEMP_OFFSET_TO_REG(int off, int mode) -{ - int factor = mode ? 5 : 10; - - off = SENSORS_LIMIT(off, LM93_TEMP_OFFSET_MIN, - mode ? LM93_TEMP_OFFSET_MAX1 : LM93_TEMP_OFFSET_MAX0); - return (u8)((off + factor/2) / factor); -} - -/* 0 <= nr <= 3 */ -static int LM93_TEMP_AUTO_OFFSET_FROM_REG(u8 reg, int nr, int mode) -{ - /* temp1-temp2 (nr=0,1) use lower nibble */ - if (nr < 2) - return LM93_TEMP_OFFSET_FROM_REG(reg & 0x0f, mode); - - /* temp3-temp4 (nr=2,3) use upper nibble */ - else - return LM93_TEMP_OFFSET_FROM_REG(reg >> 4 & 0x0f, mode); -} - -/* - * TEMP: 1/10 degrees C (0C to +15C (mode 0) or +7.5C (mode non-zero)) - * REG: 1.0C/bit (mode 0) or 0.5C/bit (mode non-zero) - * 0 <= nr <= 3 - */ -static u8 LM93_TEMP_AUTO_OFFSET_TO_REG(u8 old, int off, int nr, int mode) -{ - u8 new = LM93_TEMP_OFFSET_TO_REG(off, mode); - - /* temp1-temp2 (nr=0,1) use lower nibble */ - if (nr < 2) - return (old & 0xf0) | (new & 0x0f); - - /* temp3-temp4 (nr=2,3) use upper nibble */ - else - return (new << 4 & 0xf0) | (old & 0x0f); -} - -static int LM93_AUTO_BOOST_HYST_FROM_REGS(struct lm93_data *data, int nr, - int mode) -{ - u8 reg; - - switch (nr) { - case 0: - reg = data->boost_hyst[0] & 0x0f; - break; - case 1: - reg = data->boost_hyst[0] >> 4 & 0x0f; - break; - case 2: - reg = data->boost_hyst[1] & 0x0f; - break; - case 3: - default: - reg = data->boost_hyst[1] >> 4 & 0x0f; - break; - } - - return LM93_TEMP_FROM_REG(data->boost[nr]) - - LM93_TEMP_OFFSET_FROM_REG(reg, mode); -} - -static u8 LM93_AUTO_BOOST_HYST_TO_REG(struct lm93_data *data, long hyst, - int nr, int mode) -{ - u8 reg = LM93_TEMP_OFFSET_TO_REG( - (LM93_TEMP_FROM_REG(data->boost[nr]) - hyst), mode); - - switch (nr) { - case 0: - reg = (data->boost_hyst[0] & 0xf0) | (reg & 0x0f); - break; - case 1: - reg = (reg << 4 & 0xf0) | (data->boost_hyst[0] & 0x0f); - break; - case 2: - reg = (data->boost_hyst[1] & 0xf0) | (reg & 0x0f); - break; - case 3: - default: - reg = (reg << 4 & 0xf0) | (data->boost_hyst[1] & 0x0f); - break; - } - - return reg; -} - -/* - * PWM: 0-255 per sensors documentation - * REG: 0-13 as mapped below... right justified - */ -enum pwm_freq { LM93_PWM_MAP_HI_FREQ, LM93_PWM_MAP_LO_FREQ }; - -static int lm93_pwm_map[2][16] = { - { - 0x00, /* 0.00% */ 0x40, /* 25.00% */ - 0x50, /* 31.25% */ 0x60, /* 37.50% */ - 0x70, /* 43.75% */ 0x80, /* 50.00% */ - 0x90, /* 56.25% */ 0xa0, /* 62.50% */ - 0xb0, /* 68.75% */ 0xc0, /* 75.00% */ - 0xd0, /* 81.25% */ 0xe0, /* 87.50% */ - 0xf0, /* 93.75% */ 0xff, /* 100.00% */ - 0xff, 0xff, /* 14, 15 are reserved and should never occur */ - }, - { - 0x00, /* 0.00% */ 0x40, /* 25.00% */ - 0x49, /* 28.57% */ 0x52, /* 32.14% */ - 0x5b, /* 35.71% */ 0x64, /* 39.29% */ - 0x6d, /* 42.86% */ 0x76, /* 46.43% */ - 0x80, /* 50.00% */ 0x89, /* 53.57% */ - 0x92, /* 57.14% */ 0xb6, /* 71.43% */ - 0xdb, /* 85.71% */ 0xff, /* 100.00% */ - 0xff, 0xff, /* 14, 15 are reserved and should never occur */ - }, -}; - -static int LM93_PWM_FROM_REG(u8 reg, enum pwm_freq freq) -{ - return lm93_pwm_map[freq][reg & 0x0f]; -} - -/* round up to nearest match */ -static u8 LM93_PWM_TO_REG(int pwm, enum pwm_freq freq) -{ - int i; - for (i = 0; i < 13; i++) - if (pwm <= lm93_pwm_map[freq][i]) - break; - - /* can fall through with i==13 */ - return (u8)i; -} - -static int LM93_FAN_FROM_REG(u16 regs) -{ - const u16 count = le16_to_cpu(regs) >> 2; - return count == 0 ? -1 : count == 0x3fff ? 0 : 1350000 / count; -} - -/* - * RPM: (82.5 to 1350000) - * REG: 14-bits, LE, *left* justified - */ -static u16 LM93_FAN_TO_REG(long rpm) -{ - u16 count, regs; - - if (rpm == 0) { - count = 0x3fff; - } else { - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - count = SENSORS_LIMIT((1350000 + rpm) / rpm, 1, 0x3ffe); - } - - regs = count << 2; - return cpu_to_le16(regs); -} - -/* - * PWM FREQ: HZ - * REG: 0-7 as mapped below - */ -static int lm93_pwm_freq_map[8] = { - 22500, 96, 84, 72, 60, 48, 36, 12 -}; - -static int LM93_PWM_FREQ_FROM_REG(u8 reg) -{ - return lm93_pwm_freq_map[reg & 0x07]; -} - -/* round up to nearest match */ -static u8 LM93_PWM_FREQ_TO_REG(int freq) -{ - int i; - for (i = 7; i > 0; i--) - if (freq <= lm93_pwm_freq_map[i]) - break; - - /* can fall through with i==0 */ - return (u8)i; -} - -/* - * TIME: 1/100 seconds - * REG: 0-7 as mapped below - */ -static int lm93_spinup_time_map[8] = { - 0, 10, 25, 40, 70, 100, 200, 400, -}; - -static int LM93_SPINUP_TIME_FROM_REG(u8 reg) -{ - return lm93_spinup_time_map[reg >> 5 & 0x07]; -} - -/* round up to nearest match */ -static u8 LM93_SPINUP_TIME_TO_REG(int time) -{ - int i; - for (i = 0; i < 7; i++) - if (time <= lm93_spinup_time_map[i]) - break; - - /* can fall through with i==8 */ - return (u8)i; -} - -#define LM93_RAMP_MIN 0 -#define LM93_RAMP_MAX 75 - -static int LM93_RAMP_FROM_REG(u8 reg) -{ - return (reg & 0x0f) * 5; -} - -/* - * RAMP: 1/100 seconds - * REG: 50mS/bit 4-bits right justified - */ -static u8 LM93_RAMP_TO_REG(int ramp) -{ - ramp = SENSORS_LIMIT(ramp, LM93_RAMP_MIN, LM93_RAMP_MAX); - return (u8)((ramp + 2) / 5); -} - -/* - * PROCHOT: 0-255, 0 => 0%, 255 => > 96.6% - * REG: (same) - */ -static u8 LM93_PROCHOT_TO_REG(long prochot) -{ - prochot = SENSORS_LIMIT(prochot, 0, 255); - return (u8)prochot; -} - -/* - * PROCHOT-INTERVAL: 73 - 37200 (1/100 seconds) - * REG: 0-9 as mapped below - */ -static int lm93_interval_map[10] = { - 73, 146, 290, 580, 1170, 2330, 4660, 9320, 18600, 37200, -}; - -static int LM93_INTERVAL_FROM_REG(u8 reg) -{ - return lm93_interval_map[reg & 0x0f]; -} - -/* round up to nearest match */ -static u8 LM93_INTERVAL_TO_REG(long interval) -{ - int i; - for (i = 0; i < 9; i++) - if (interval <= lm93_interval_map[i]) - break; - - /* can fall through with i==9 */ - return (u8)i; -} - -/* - * GPIO: 0-255, GPIO0 is LSB - * REG: inverted - */ -static unsigned LM93_GPI_FROM_REG(u8 reg) -{ - return ~reg & 0xff; -} - -/* - * alarm bitmask definitions - * The LM93 has nearly 64 bits of error status... I've pared that down to - * what I think is a useful subset in order to fit it into 32 bits. - * - * Especially note that the #VRD_HOT alarms are missing because we provide - * that information as values in another sysfs file. - * - * If libsensors is extended to support 64 bit values, this could be revisited. - */ -#define LM93_ALARM_IN1 0x00000001 -#define LM93_ALARM_IN2 0x00000002 -#define LM93_ALARM_IN3 0x00000004 -#define LM93_ALARM_IN4 0x00000008 -#define LM93_ALARM_IN5 0x00000010 -#define LM93_ALARM_IN6 0x00000020 -#define LM93_ALARM_IN7 0x00000040 -#define LM93_ALARM_IN8 0x00000080 -#define LM93_ALARM_IN9 0x00000100 -#define LM93_ALARM_IN10 0x00000200 -#define LM93_ALARM_IN11 0x00000400 -#define LM93_ALARM_IN12 0x00000800 -#define LM93_ALARM_IN13 0x00001000 -#define LM93_ALARM_IN14 0x00002000 -#define LM93_ALARM_IN15 0x00004000 -#define LM93_ALARM_IN16 0x00008000 -#define LM93_ALARM_FAN1 0x00010000 -#define LM93_ALARM_FAN2 0x00020000 -#define LM93_ALARM_FAN3 0x00040000 -#define LM93_ALARM_FAN4 0x00080000 -#define LM93_ALARM_PH1_ERR 0x00100000 -#define LM93_ALARM_PH2_ERR 0x00200000 -#define LM93_ALARM_SCSI1_ERR 0x00400000 -#define LM93_ALARM_SCSI2_ERR 0x00800000 -#define LM93_ALARM_DVDDP1_ERR 0x01000000 -#define LM93_ALARM_DVDDP2_ERR 0x02000000 -#define LM93_ALARM_D1_ERR 0x04000000 -#define LM93_ALARM_D2_ERR 0x08000000 -#define LM93_ALARM_TEMP1 0x10000000 -#define LM93_ALARM_TEMP2 0x20000000 -#define LM93_ALARM_TEMP3 0x40000000 - -static unsigned LM93_ALARMS_FROM_REG(struct block1_t b1) -{ - unsigned result; - result = b1.host_status_2 & 0x3f; - - if (vccp_limit_type[0]) - result |= (b1.host_status_4 & 0x10) << 2; - else - result |= b1.host_status_2 & 0x40; - - if (vccp_limit_type[1]) - result |= (b1.host_status_4 & 0x20) << 2; - else - result |= b1.host_status_2 & 0x80; - - result |= b1.host_status_3 << 8; - result |= (b1.fan_status & 0x0f) << 16; - result |= (b1.p1_prochot_status & 0x80) << 13; - result |= (b1.p2_prochot_status & 0x80) << 14; - result |= (b1.host_status_4 & 0xfc) << 20; - result |= (b1.host_status_1 & 0x07) << 28; - return result; -} - -#define MAX_RETRIES 5 - -static u8 lm93_read_byte(struct i2c_client *client, u8 reg) -{ - int value, i; - - /* retry in case of read errors */ - for (i = 1; i <= MAX_RETRIES; i++) { - value = i2c_smbus_read_byte_data(client, reg); - if (value >= 0) { - return value; - } else { - dev_warn(&client->dev, "lm93: read byte data failed, " - "address 0x%02x.\n", reg); - mdelay(i + 3); - } - - } - - /* what to return in case of error? */ - dev_err(&client->dev, "lm93: All read byte retries failed!!\n"); - return 0; -} - -static int lm93_write_byte(struct i2c_client *client, u8 reg, u8 value) -{ - int result; - - /* how to handle write errors? */ - result = i2c_smbus_write_byte_data(client, reg, value); - - if (result < 0) - dev_warn(&client->dev, "lm93: write byte data failed, " - "0x%02x at address 0x%02x.\n", value, reg); - - return result; -} - -static u16 lm93_read_word(struct i2c_client *client, u8 reg) -{ - int value, i; - - /* retry in case of read errors */ - for (i = 1; i <= MAX_RETRIES; i++) { - value = i2c_smbus_read_word_data(client, reg); - if (value >= 0) { - return value; - } else { - dev_warn(&client->dev, "lm93: read word data failed, " - "address 0x%02x.\n", reg); - mdelay(i + 3); - } - - } - - /* what to return in case of error? */ - dev_err(&client->dev, "lm93: All read word retries failed!!\n"); - return 0; -} - -static int lm93_write_word(struct i2c_client *client, u8 reg, u16 value) -{ - int result; - - /* how to handle write errors? */ - result = i2c_smbus_write_word_data(client, reg, value); - - if (result < 0) - dev_warn(&client->dev, "lm93: write word data failed, " - "0x%04x at address 0x%02x.\n", value, reg); - - return result; -} - -static u8 lm93_block_buffer[I2C_SMBUS_BLOCK_MAX]; - -/* - * read block data into values, retry if not expected length - * fbn => index to lm93_block_read_cmds table - * (Fixed Block Number - section 14.5.2 of LM93 datasheet) - */ -static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values) -{ - int i, result = 0; - - for (i = 1; i <= MAX_RETRIES; i++) { - result = i2c_smbus_read_block_data(client, - lm93_block_read_cmds[fbn].cmd, lm93_block_buffer); - - if (result == lm93_block_read_cmds[fbn].len) { - break; - } else { - dev_warn(&client->dev, "lm93: block read data failed, " - "command 0x%02x.\n", - lm93_block_read_cmds[fbn].cmd); - mdelay(i + 3); - } - } - - if (result == lm93_block_read_cmds[fbn].len) { - memcpy(values, lm93_block_buffer, - lm93_block_read_cmds[fbn].len); - } else { - /* what to do in case of error? */ - } -} - -static struct lm93_data *lm93_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - const unsigned long interval = HZ + (HZ / 2); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + interval) || - !data->valid) { - - data->update(data, client); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - return data; -} - -/* update routine for data that has no corresponding SMBus block command */ -static void lm93_update_client_common(struct lm93_data *data, - struct i2c_client *client) -{ - int i; - u8 *ptr; - - /* temp1 - temp4: limits */ - for (i = 0; i < 4; i++) { - data->temp_lim[i].min = - lm93_read_byte(client, LM93_REG_TEMP_MIN(i)); - data->temp_lim[i].max = - lm93_read_byte(client, LM93_REG_TEMP_MAX(i)); - } - - /* config register */ - data->config = lm93_read_byte(client, LM93_REG_CONFIG); - - /* vid1 - vid2: values */ - for (i = 0; i < 2; i++) - data->vid[i] = lm93_read_byte(client, LM93_REG_VID(i)); - - /* prochot1 - prochot2: limits */ - for (i = 0; i < 2; i++) - data->prochot_max[i] = lm93_read_byte(client, - LM93_REG_PROCHOT_MAX(i)); - - /* vccp1 - vccp2: VID relative limits */ - for (i = 0; i < 2; i++) - data->vccp_limits[i] = lm93_read_byte(client, - LM93_REG_VCCP_LIMIT_OFF(i)); - - /* GPIO input state */ - data->gpi = lm93_read_byte(client, LM93_REG_GPI); - - /* #PROCHOT override state */ - data->prochot_override = lm93_read_byte(client, - LM93_REG_PROCHOT_OVERRIDE); - - /* #PROCHOT intervals */ - data->prochot_interval = lm93_read_byte(client, - LM93_REG_PROCHOT_INTERVAL); - - /* Fan Boost Temperature registers */ - for (i = 0; i < 4; i++) - data->boost[i] = lm93_read_byte(client, LM93_REG_BOOST(i)); - - /* Fan Boost Temperature Hyst. registers */ - data->boost_hyst[0] = lm93_read_byte(client, LM93_REG_BOOST_HYST_12); - data->boost_hyst[1] = lm93_read_byte(client, LM93_REG_BOOST_HYST_34); - - /* Temperature Zone Min. PWM & Hysteresis registers */ - data->auto_pwm_min_hyst[0] = - lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_12); - data->auto_pwm_min_hyst[1] = - lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_34); - - /* #PROCHOT & #VRDHOT PWM Ramp Control register */ - data->pwm_ramp_ctl = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL); - - /* misc setup registers */ - data->sfc1 = lm93_read_byte(client, LM93_REG_SFC1); - data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); - data->sf_tach_to_pwm = lm93_read_byte(client, - LM93_REG_SF_TACH_TO_PWM); - - /* write back alarm values to clear */ - for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++) - lm93_write_byte(client, LM93_REG_HOST_ERROR_1 + i, *(ptr + i)); -} - -/* update routine which uses SMBus block data commands */ -static void lm93_update_client_full(struct lm93_data *data, - struct i2c_client *client) -{ - dev_dbg(&client->dev, "starting device update (block data enabled)\n"); - - /* in1 - in16: values & limits */ - lm93_read_block(client, 3, (u8 *)(data->block3)); - lm93_read_block(client, 7, (u8 *)(data->block7)); - - /* temp1 - temp4: values */ - lm93_read_block(client, 2, (u8 *)(data->block2)); - - /* prochot1 - prochot2: values */ - lm93_read_block(client, 4, (u8 *)(data->block4)); - - /* fan1 - fan4: values & limits */ - lm93_read_block(client, 5, (u8 *)(data->block5)); - lm93_read_block(client, 8, (u8 *)(data->block8)); - - /* pmw control registers */ - lm93_read_block(client, 9, (u8 *)(data->block9)); - - /* alarm values */ - lm93_read_block(client, 1, (u8 *)(&data->block1)); - - /* auto/pwm registers */ - lm93_read_block(client, 10, (u8 *)(&data->block10)); - - lm93_update_client_common(data, client); -} - -/* update routine which uses SMBus byte/word data commands only */ -static void lm93_update_client_min(struct lm93_data *data, - struct i2c_client *client) -{ - int i, j; - u8 *ptr; - - dev_dbg(&client->dev, "starting device update (block data disabled)\n"); - - /* in1 - in16: values & limits */ - for (i = 0; i < 16; i++) { - data->block3[i] = - lm93_read_byte(client, LM93_REG_IN(i)); - data->block7[i].min = - lm93_read_byte(client, LM93_REG_IN_MIN(i)); - data->block7[i].max = - lm93_read_byte(client, LM93_REG_IN_MAX(i)); - } - - /* temp1 - temp4: values */ - for (i = 0; i < 4; i++) { - data->block2[i] = - lm93_read_byte(client, LM93_REG_TEMP(i)); - } - - /* prochot1 - prochot2: values */ - for (i = 0; i < 2; i++) { - data->block4[i].cur = - lm93_read_byte(client, LM93_REG_PROCHOT_CUR(i)); - data->block4[i].avg = - lm93_read_byte(client, LM93_REG_PROCHOT_AVG(i)); - } - - /* fan1 - fan4: values & limits */ - for (i = 0; i < 4; i++) { - data->block5[i] = - lm93_read_word(client, LM93_REG_FAN(i)); - data->block8[i] = - lm93_read_word(client, LM93_REG_FAN_MIN(i)); - } - - /* pwm control registers */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 4; j++) { - data->block9[i][j] = - lm93_read_byte(client, LM93_REG_PWM_CTL(i, j)); - } - } - - /* alarm values */ - for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++) { - *(ptr + i) = - lm93_read_byte(client, LM93_REG_HOST_ERROR_1 + i); - } - - /* auto/pwm (base temp) registers */ - for (i = 0; i < 4; i++) { - data->block10.base[i] = - lm93_read_byte(client, LM93_REG_TEMP_BASE(i)); - } - - /* auto/pwm (offset temp) registers */ - for (i = 0; i < 12; i++) { - data->block10.offset[i] = - lm93_read_byte(client, LM93_REG_TEMP_OFFSET(i)); - } - - lm93_update_client_common(data, client); -} - -/* following are the sysfs callback functions */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_IN_FROM_REG(nr, data->block3[nr])); -} - -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 4); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 5); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 6); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 7); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in, NULL, 8); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in, NULL, 9); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_in, NULL, 10); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_in, NULL, 11); -static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_in, NULL, 12); -static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_in, NULL, 13); -static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_in, NULL, 14); -static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in, NULL, 15); - -static ssize_t show_in_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - int vccp = nr - 6; - long rc, vid; - - if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) { - vid = LM93_VID_FROM_REG(data->vid[vccp]); - rc = LM93_IN_MIN_FROM_REG(data->vccp_limits[vccp], vid); - } else { - rc = LM93_IN_FROM_REG(nr, data->block7[nr].min); - } - return sprintf(buf, "%ld\n", rc); -} - -static ssize_t store_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - int vccp = nr - 6; - long vid; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) { - vid = LM93_VID_FROM_REG(data->vid[vccp]); - data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0xf0) | - LM93_IN_REL_TO_REG(val, 0, vid); - lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp), - data->vccp_limits[vccp]); - } else { - data->block7[nr].min = LM93_IN_TO_REG(nr, val); - lm93_write_byte(client, LM93_REG_IN_MIN(nr), - data->block7[nr].min); - } - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 0); -static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 1); -static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 2); -static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 3); -static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 4); -static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 5); -static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 6); -static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 7); -static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 8); -static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 9); -static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 10); -static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 11); -static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 12); -static SENSOR_DEVICE_ATTR(in14_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 13); -static SENSOR_DEVICE_ATTR(in15_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 14); -static SENSOR_DEVICE_ATTR(in16_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 15); - -static ssize_t show_in_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - int vccp = nr - 6; - long rc, vid; - - if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) { - vid = LM93_VID_FROM_REG(data->vid[vccp]); - rc = LM93_IN_MAX_FROM_REG(data->vccp_limits[vccp], vid); - } else { - rc = LM93_IN_FROM_REG(nr, data->block7[nr].max); - } - return sprintf(buf, "%ld\n", rc); -} - -static ssize_t store_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - int vccp = nr - 6; - long vid; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if ((nr == 6 || nr == 7) && vccp_limit_type[vccp]) { - vid = LM93_VID_FROM_REG(data->vid[vccp]); - data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0x0f) | - LM93_IN_REL_TO_REG(val, 1, vid); - lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp), - data->vccp_limits[vccp]); - } else { - data->block7[nr].max = LM93_IN_TO_REG(nr, val); - lm93_write_byte(client, LM93_REG_IN_MAX(nr), - data->block7[nr].max); - } - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 0); -static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 1); -static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 2); -static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 3); -static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 4); -static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 5); -static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 6); -static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 7); -static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 8); -static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 9); -static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 10); -static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 11); -static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 12); -static SENSOR_DEVICE_ATTR(in14_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 13); -static SENSOR_DEVICE_ATTR(in15_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 14); -static SENSOR_DEVICE_ATTR(in16_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 15); - -static ssize_t show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block2[nr])); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].min)); -} - -static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_lim[nr].min = LM93_TEMP_TO_REG(val); - lm93_write_byte(client, LM93_REG_TEMP_MIN(nr), data->temp_lim[nr].min); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, - show_temp_min, store_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, - show_temp_min, store_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, - show_temp_min, store_temp_min, 2); - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->temp_lim[nr].max)); -} - -static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_lim[nr].max = LM93_TEMP_TO_REG(val); - lm93_write_byte(client, LM93_REG_TEMP_MAX(nr), data->temp_lim[nr].max); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, - show_temp_max, store_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, - show_temp_max, store_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, - show_temp_max, store_temp_max, 2); - -static ssize_t show_temp_auto_base(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->block10.base[nr])); -} - -static ssize_t store_temp_auto_base(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->block10.base[nr] = LM93_TEMP_TO_REG(val); - lm93_write_byte(client, LM93_REG_TEMP_BASE(nr), data->block10.base[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_auto_base, S_IWUSR | S_IRUGO, - show_temp_auto_base, store_temp_auto_base, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_base, S_IWUSR | S_IRUGO, - show_temp_auto_base, store_temp_auto_base, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_base, S_IWUSR | S_IRUGO, - show_temp_auto_base, store_temp_auto_base, 2); - -static ssize_t show_temp_auto_boost(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_TEMP_FROM_REG(data->boost[nr])); -} - -static ssize_t store_temp_auto_boost(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->boost[nr] = LM93_TEMP_TO_REG(val); - lm93_write_byte(client, LM93_REG_BOOST(nr), data->boost[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_auto_boost, S_IWUSR | S_IRUGO, - show_temp_auto_boost, store_temp_auto_boost, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_boost, S_IWUSR | S_IRUGO, - show_temp_auto_boost, store_temp_auto_boost, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_boost, S_IWUSR | S_IRUGO, - show_temp_auto_boost, store_temp_auto_boost, 2); - -static ssize_t show_temp_auto_boost_hyst(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr); - return sprintf(buf, "%d\n", - LM93_AUTO_BOOST_HYST_FROM_REGS(data, nr, mode)); -} - -static ssize_t store_temp_auto_boost_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - /* force 0.5C/bit mode */ - data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); - data->sfc2 |= ((nr < 2) ? 0x10 : 0x20); - lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); - data->boost_hyst[nr/2] = LM93_AUTO_BOOST_HYST_TO_REG(data, val, nr, 1); - lm93_write_byte(client, LM93_REG_BOOST_HYST(nr), - data->boost_hyst[nr/2]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_auto_boost_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_boost_hyst, - store_temp_auto_boost_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_boost_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_boost_hyst, - store_temp_auto_boost_hyst, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_boost_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_boost_hyst, - store_temp_auto_boost_hyst, 2); - -static ssize_t show_temp_auto_offset(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); - int nr = s_attr->index; - int ofs = s_attr->nr; - struct lm93_data *data = lm93_update_device(dev); - int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr); - return sprintf(buf, "%d\n", - LM93_TEMP_AUTO_OFFSET_FROM_REG(data->block10.offset[ofs], - nr, mode)); -} - -static ssize_t store_temp_auto_offset(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); - int nr = s_attr->index; - int ofs = s_attr->nr; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - /* force 0.5C/bit mode */ - data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); - data->sfc2 |= ((nr < 2) ? 0x10 : 0x20); - lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); - data->block10.offset[ofs] = LM93_TEMP_AUTO_OFFSET_TO_REG( - data->block10.offset[ofs], val, nr, 1); - lm93_write_byte(client, LM93_REG_TEMP_OFFSET(ofs), - data->block10.offset[ofs]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset1, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset2, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 1, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset3, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 2, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset4, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 3, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset5, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 4, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset6, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 5, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset7, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 6, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset8, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 7, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset9, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 8, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset10, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 9, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset11, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 10, 0); -static SENSOR_DEVICE_ATTR_2(temp1_auto_offset12, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 11, 0); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset1, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 0, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset2, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 1, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset3, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 2, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset4, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 3, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset5, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 4, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset6, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 5, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset7, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 6, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset8, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 7, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset9, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 8, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset10, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 9, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset11, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 10, 1); -static SENSOR_DEVICE_ATTR_2(temp2_auto_offset12, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 11, 1); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset1, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 0, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset2, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 1, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset3, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 2, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset4, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 3, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset5, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 4, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset6, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 5, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset7, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 6, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset8, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 7, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset9, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 8, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset10, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 9, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset11, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 10, 2); -static SENSOR_DEVICE_ATTR_2(temp3_auto_offset12, S_IWUSR | S_IRUGO, - show_temp_auto_offset, store_temp_auto_offset, 11, 2); - -static ssize_t show_temp_auto_pwm_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - u8 reg, ctl4; - struct lm93_data *data = lm93_update_device(dev); - reg = data->auto_pwm_min_hyst[nr/2] >> 4 & 0x0f; - ctl4 = data->block9[nr][LM93_PWM_CTL4]; - return sprintf(buf, "%d\n", LM93_PWM_FROM_REG(reg, (ctl4 & 0x07) ? - LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ)); -} - -static ssize_t store_temp_auto_pwm_min(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 reg, ctl4; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - reg = lm93_read_byte(client, LM93_REG_PWM_MIN_HYST(nr)); - ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4)); - reg = (reg & 0x0f) | - LM93_PWM_TO_REG(val, (ctl4 & 0x07) ? - LM93_PWM_MAP_LO_FREQ : - LM93_PWM_MAP_HI_FREQ) << 4; - data->auto_pwm_min_hyst[nr/2] = reg; - lm93_write_byte(client, LM93_REG_PWM_MIN_HYST(nr), reg); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_auto_pwm_min, S_IWUSR | S_IRUGO, - show_temp_auto_pwm_min, - store_temp_auto_pwm_min, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_pwm_min, S_IWUSR | S_IRUGO, - show_temp_auto_pwm_min, - store_temp_auto_pwm_min, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_pwm_min, S_IWUSR | S_IRUGO, - show_temp_auto_pwm_min, - store_temp_auto_pwm_min, 2); - -static ssize_t show_temp_auto_offset_hyst(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr); - return sprintf(buf, "%d\n", LM93_TEMP_OFFSET_FROM_REG( - data->auto_pwm_min_hyst[nr / 2], mode)); -} - -static ssize_t store_temp_auto_offset_hyst(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - /* force 0.5C/bit mode */ - data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); - data->sfc2 |= ((nr < 2) ? 0x10 : 0x20); - lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); - reg = data->auto_pwm_min_hyst[nr/2]; - reg = (reg & 0xf0) | (LM93_TEMP_OFFSET_TO_REG(val, 1) & 0x0f); - data->auto_pwm_min_hyst[nr/2] = reg; - lm93_write_byte(client, LM93_REG_PWM_MIN_HYST(nr), reg); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_auto_offset_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_offset_hyst, - store_temp_auto_offset_hyst, 0); -static SENSOR_DEVICE_ATTR(temp2_auto_offset_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_offset_hyst, - store_temp_auto_offset_hyst, 1); -static SENSOR_DEVICE_ATTR(temp3_auto_offset_hyst, S_IWUSR | S_IRUGO, - show_temp_auto_offset_hyst, - store_temp_auto_offset_hyst, 2); - -static ssize_t show_fan_input(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr); - int nr = s_attr->index; - struct lm93_data *data = lm93_update_device(dev); - - return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block5[nr])); -} - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3); - -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - - return sprintf(buf, "%d\n", LM93_FAN_FROM_REG(data->block8[nr])); -} - -static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->block8[nr] = LM93_FAN_TO_REG(val); - lm93_write_word(client, LM93_REG_FAN_MIN(nr), data->block8[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 3); - -/* - * some tedious bit-twiddling here to deal with the register format: - * - * data->sf_tach_to_pwm: (tach to pwm mapping bits) - * - * bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 - * T4:P2 T4:P1 T3:P2 T3:P1 T2:P2 T2:P1 T1:P2 T1:P1 - * - * data->sfc2: (enable bits) - * - * bit | 3 | 2 | 1 | 0 - * T4 T3 T2 T1 - */ - -static ssize_t show_fan_smart_tach(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - long rc = 0; - int mapping; - - /* extract the relevant mapping */ - mapping = (data->sf_tach_to_pwm >> (nr * 2)) & 0x03; - - /* if there's a mapping and it's enabled */ - if (mapping && ((data->sfc2 >> nr) & 0x01)) - rc = mapping; - return sprintf(buf, "%ld\n", rc); -} - -/* - * helper function - must grab data->update_lock before calling - * fan is 0-3, indicating fan1-fan4 - */ -static void lm93_write_fan_smart_tach(struct i2c_client *client, - struct lm93_data *data, int fan, long value) -{ - /* insert the new mapping and write it out */ - data->sf_tach_to_pwm = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM); - data->sf_tach_to_pwm &= ~(0x3 << fan * 2); - data->sf_tach_to_pwm |= value << fan * 2; - lm93_write_byte(client, LM93_REG_SF_TACH_TO_PWM, data->sf_tach_to_pwm); - - /* insert the enable bit and write it out */ - data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); - if (value) - data->sfc2 |= 1 << fan; - else - data->sfc2 &= ~(1 << fan); - lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); -} - -static ssize_t store_fan_smart_tach(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - /* sanity test, ignore the write otherwise */ - if (0 <= val && val <= 2) { - /* can't enable if pwm freq is 22.5KHz */ - if (val) { - u8 ctl4 = lm93_read_byte(client, - LM93_REG_PWM_CTL(val - 1, LM93_PWM_CTL4)); - if ((ctl4 & 0x07) == 0) - val = 0; - } - lm93_write_fan_smart_tach(client, data, nr, val); - } - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 0); -static SENSOR_DEVICE_ATTR(fan2_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 1); -static SENSOR_DEVICE_ATTR(fan3_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 2); -static SENSOR_DEVICE_ATTR(fan4_smart_tach, S_IWUSR | S_IRUGO, - show_fan_smart_tach, store_fan_smart_tach, 3); - -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - u8 ctl2, ctl4; - long rc; - - ctl2 = data->block9[nr][LM93_PWM_CTL2]; - ctl4 = data->block9[nr][LM93_PWM_CTL4]; - if (ctl2 & 0x01) /* show user commanded value if enabled */ - rc = data->pwm_override[nr]; - else /* show present h/w value if manual pwm disabled */ - rc = LM93_PWM_FROM_REG(ctl2 >> 4, (ctl4 & 0x07) ? - LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ); - return sprintf(buf, "%ld\n", rc); -} - -static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ctl2, ctl4; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ctl2 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2)); - ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4)); - ctl2 = (ctl2 & 0x0f) | LM93_PWM_TO_REG(val, (ctl4 & 0x07) ? - LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ) << 4; - /* save user commanded value */ - data->pwm_override[nr] = LM93_PWM_FROM_REG(ctl2 >> 4, - (ctl4 & 0x07) ? LM93_PWM_MAP_LO_FREQ : - LM93_PWM_MAP_HI_FREQ); - lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2), ctl2); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); - -static ssize_t show_pwm_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - u8 ctl2; - long rc; - - ctl2 = data->block9[nr][LM93_PWM_CTL2]; - if (ctl2 & 0x01) /* manual override enabled ? */ - rc = ((ctl2 & 0xF0) == 0xF0) ? 0 : 1; - else - rc = 2; - return sprintf(buf, "%ld\n", rc); -} - -static ssize_t store_pwm_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ctl2; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ctl2 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2)); - - switch (val) { - case 0: - ctl2 |= 0xF1; /* enable manual override, set PWM to max */ - break; - case 1: - ctl2 |= 0x01; /* enable manual override */ - break; - case 2: - ctl2 &= ~0x01; /* disable manual override */ - break; - default: - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL2), ctl2); - mutex_unlock(&data->update_lock); - return count; -} - -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 ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - u8 ctl4; - - ctl4 = data->block9[nr][LM93_PWM_CTL4]; - return sprintf(buf, "%d\n", LM93_PWM_FREQ_FROM_REG(ctl4)); -} - -/* - * helper function - must grab data->update_lock before calling - * pwm is 0-1, indicating pwm1-pwm2 - * this disables smart tach for all tach channels bound to the given pwm - */ -static void lm93_disable_fan_smart_tach(struct i2c_client *client, - struct lm93_data *data, int pwm) -{ - int mapping = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM); - int mask; - - /* collapse the mapping into a mask of enable bits */ - mapping = (mapping >> pwm) & 0x55; - mask = mapping & 0x01; - mask |= (mapping & 0x04) >> 1; - mask |= (mapping & 0x10) >> 2; - mask |= (mapping & 0x40) >> 3; - - /* disable smart tach according to the mask */ - data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2); - data->sfc2 &= ~mask; - lm93_write_byte(client, LM93_REG_SFC2, data->sfc2); -} - -static ssize_t store_pwm_freq(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ctl4; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4)); - ctl4 = (ctl4 & 0xf8) | LM93_PWM_FREQ_TO_REG(val); - data->block9[nr][LM93_PWM_CTL4] = ctl4; - /* ctl4 == 0 -> 22.5KHz -> disable smart tach */ - if (!ctl4) - lm93_disable_fan_smart_tach(client, data, nr); - lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4), ctl4); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_freq, S_IWUSR | S_IRUGO, - show_pwm_freq, store_pwm_freq, 0); -static SENSOR_DEVICE_ATTR(pwm2_freq, S_IWUSR | S_IRUGO, - show_pwm_freq, store_pwm_freq, 1); - -static ssize_t show_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", data->block9[nr][LM93_PWM_CTL1]); -} - -static ssize_t store_pwm_auto_channels(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->block9[nr][LM93_PWM_CTL1] = SENSORS_LIMIT(val, 0, 255); - lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL1), - data->block9[nr][LM93_PWM_CTL1]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_auto_channels, S_IWUSR | S_IRUGO, - show_pwm_auto_channels, store_pwm_auto_channels, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_channels, S_IWUSR | S_IRUGO, - show_pwm_auto_channels, store_pwm_auto_channels, 1); - -static ssize_t show_pwm_auto_spinup_min(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - u8 ctl3, ctl4; - - ctl3 = data->block9[nr][LM93_PWM_CTL3]; - ctl4 = data->block9[nr][LM93_PWM_CTL4]; - return sprintf(buf, "%d\n", - LM93_PWM_FROM_REG(ctl3 & 0x0f, (ctl4 & 0x07) ? - LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ)); -} - -static ssize_t store_pwm_auto_spinup_min(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ctl3, ctl4; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ctl3 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3)); - ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4)); - ctl3 = (ctl3 & 0xf0) | LM93_PWM_TO_REG(val, (ctl4 & 0x07) ? - LM93_PWM_MAP_LO_FREQ : - LM93_PWM_MAP_HI_FREQ); - data->block9[nr][LM93_PWM_CTL3] = ctl3; - lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_min, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_min, - store_pwm_auto_spinup_min, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_min, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_min, - store_pwm_auto_spinup_min, 1); - -static ssize_t show_pwm_auto_spinup_time(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_SPINUP_TIME_FROM_REG( - data->block9[nr][LM93_PWM_CTL3])); -} - -static ssize_t store_pwm_auto_spinup_time(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ctl3; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ctl3 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3)); - ctl3 = (ctl3 & 0x1f) | (LM93_SPINUP_TIME_TO_REG(val) << 5 & 0xe0); - data->block9[nr][LM93_PWM_CTL3] = ctl3; - lm93_write_byte(client, LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_time, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_time, - store_pwm_auto_spinup_time, 0); -static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_time, S_IWUSR | S_IRUGO, - show_pwm_auto_spinup_time, - store_pwm_auto_spinup_time, 1); - -static ssize_t show_pwm_auto_prochot_ramp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", - LM93_RAMP_FROM_REG(data->pwm_ramp_ctl >> 4 & 0x0f)); -} - -static ssize_t store_pwm_auto_prochot_ramp(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ramp; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ramp = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL); - ramp = (ramp & 0x0f) | (LM93_RAMP_TO_REG(val) << 4 & 0xf0); - lm93_write_byte(client, LM93_REG_PWM_RAMP_CTL, ramp); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(pwm_auto_prochot_ramp, S_IRUGO | S_IWUSR, - show_pwm_auto_prochot_ramp, - store_pwm_auto_prochot_ramp); - -static ssize_t show_pwm_auto_vrdhot_ramp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", - LM93_RAMP_FROM_REG(data->pwm_ramp_ctl & 0x0f)); -} - -static ssize_t store_pwm_auto_vrdhot_ramp(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 ramp; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - ramp = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL); - ramp = (ramp & 0xf0) | (LM93_RAMP_TO_REG(val) & 0x0f); - lm93_write_byte(client, LM93_REG_PWM_RAMP_CTL, ramp); - mutex_unlock(&data->update_lock); - return 0; -} - -static DEVICE_ATTR(pwm_auto_vrdhot_ramp, S_IRUGO | S_IWUSR, - show_pwm_auto_vrdhot_ramp, - store_pwm_auto_vrdhot_ramp); - -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_VID_FROM_REG(data->vid[nr])); -} - -static SENSOR_DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL, 0); -static SENSOR_DEVICE_ATTR(cpu1_vid, S_IRUGO, show_vid, NULL, 1); - -static ssize_t show_prochot(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", data->block4[nr].cur); -} - -static SENSOR_DEVICE_ATTR(prochot1, S_IRUGO, show_prochot, NULL, 0); -static SENSOR_DEVICE_ATTR(prochot2, S_IRUGO, show_prochot, NULL, 1); - -static ssize_t show_prochot_avg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", data->block4[nr].avg); -} - -static SENSOR_DEVICE_ATTR(prochot1_avg, S_IRUGO, show_prochot_avg, NULL, 0); -static SENSOR_DEVICE_ATTR(prochot2_avg, S_IRUGO, show_prochot_avg, NULL, 1); - -static ssize_t show_prochot_max(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", data->prochot_max[nr]); -} - -static ssize_t store_prochot_max(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->prochot_max[nr] = LM93_PROCHOT_TO_REG(val); - lm93_write_byte(client, LM93_REG_PROCHOT_MAX(nr), - data->prochot_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(prochot1_max, S_IWUSR | S_IRUGO, - show_prochot_max, store_prochot_max, 0); -static SENSOR_DEVICE_ATTR(prochot2_max, S_IWUSR | S_IRUGO, - show_prochot_max, store_prochot_max, 1); - -static const u8 prochot_override_mask[] = { 0x80, 0x40 }; - -static ssize_t show_prochot_override(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", - (data->prochot_override & prochot_override_mask[nr]) ? 1 : 0); -} - -static ssize_t store_prochot_override(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (val) - data->prochot_override |= prochot_override_mask[nr]; - else - data->prochot_override &= (~prochot_override_mask[nr]); - lm93_write_byte(client, LM93_REG_PROCHOT_OVERRIDE, - data->prochot_override); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(prochot1_override, S_IWUSR | S_IRUGO, - show_prochot_override, store_prochot_override, 0); -static SENSOR_DEVICE_ATTR(prochot2_override, S_IWUSR | S_IRUGO, - show_prochot_override, store_prochot_override, 1); - -static ssize_t show_prochot_interval(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - u8 tmp; - if (nr == 1) - tmp = (data->prochot_interval & 0xf0) >> 4; - else - tmp = data->prochot_interval & 0x0f; - return sprintf(buf, "%d\n", LM93_INTERVAL_FROM_REG(tmp)); -} - -static ssize_t store_prochot_interval(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - u8 tmp; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - tmp = lm93_read_byte(client, LM93_REG_PROCHOT_INTERVAL); - if (nr == 1) - tmp = (tmp & 0x0f) | (LM93_INTERVAL_TO_REG(val) << 4); - else - tmp = (tmp & 0xf0) | LM93_INTERVAL_TO_REG(val); - data->prochot_interval = tmp; - lm93_write_byte(client, LM93_REG_PROCHOT_INTERVAL, tmp); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(prochot1_interval, S_IWUSR | S_IRUGO, - show_prochot_interval, store_prochot_interval, 0); -static SENSOR_DEVICE_ATTR(prochot2_interval, S_IWUSR | S_IRUGO, - show_prochot_interval, store_prochot_interval, 1); - -static ssize_t show_prochot_override_duty_cycle(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", data->prochot_override & 0x0f); -} - -static ssize_t store_prochot_override_duty_cycle(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->prochot_override = (data->prochot_override & 0xf0) | - SENSORS_LIMIT(val, 0, 15); - lm93_write_byte(client, LM93_REG_PROCHOT_OVERRIDE, - data->prochot_override); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(prochot_override_duty_cycle, S_IRUGO | S_IWUSR, - show_prochot_override_duty_cycle, - store_prochot_override_duty_cycle); - -static ssize_t show_prochot_short(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", (data->config & 0x10) ? 1 : 0); -} - -static ssize_t store_prochot_short(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (val) - data->config |= 0x10; - else - data->config &= ~0x10; - lm93_write_byte(client, LM93_REG_CONFIG, data->config); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(prochot_short, S_IRUGO | S_IWUSR, - show_prochot_short, store_prochot_short); - -static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = (to_sensor_dev_attr(attr))->index; - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", - data->block1.host_status_1 & (1 << (nr + 4)) ? 1 : 0); -} - -static SENSOR_DEVICE_ATTR(vrdhot1, S_IRUGO, show_vrdhot, NULL, 0); -static SENSOR_DEVICE_ATTR(vrdhot2, S_IRUGO, show_vrdhot, NULL, 1); - -static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_GPI_FROM_REG(data->gpi)); -} - -static DEVICE_ATTR(gpio, S_IRUGO, show_gpio, NULL); - -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm93_data *data = lm93_update_device(dev); - return sprintf(buf, "%d\n", LM93_ALARMS_FROM_REG(data->block1)); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static struct attribute *lm93_attrs[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_in13_input.dev_attr.attr, - &sensor_dev_attr_in14_input.dev_attr.attr, - &sensor_dev_attr_in15_input.dev_attr.attr, - &sensor_dev_attr_in16_input.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in10_min.dev_attr.attr, - &sensor_dev_attr_in11_min.dev_attr.attr, - &sensor_dev_attr_in12_min.dev_attr.attr, - &sensor_dev_attr_in13_min.dev_attr.attr, - &sensor_dev_attr_in14_min.dev_attr.attr, - &sensor_dev_attr_in15_min.dev_attr.attr, - &sensor_dev_attr_in16_min.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in10_max.dev_attr.attr, - &sensor_dev_attr_in11_max.dev_attr.attr, - &sensor_dev_attr_in12_max.dev_attr.attr, - &sensor_dev_attr_in13_max.dev_attr.attr, - &sensor_dev_attr_in14_max.dev_attr.attr, - &sensor_dev_attr_in15_max.dev_attr.attr, - &sensor_dev_attr_in16_max.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp1_auto_base.dev_attr.attr, - &sensor_dev_attr_temp2_auto_base.dev_attr.attr, - &sensor_dev_attr_temp3_auto_base.dev_attr.attr, - &sensor_dev_attr_temp1_auto_boost.dev_attr.attr, - &sensor_dev_attr_temp2_auto_boost.dev_attr.attr, - &sensor_dev_attr_temp3_auto_boost.dev_attr.attr, - &sensor_dev_attr_temp1_auto_boost_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_auto_boost_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_auto_boost_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset1.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset2.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset3.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset4.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset5.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset6.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset7.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset8.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset9.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset10.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset11.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset12.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset1.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset2.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset3.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset4.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset5.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset6.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset7.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset8.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset9.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset10.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset11.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset12.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset1.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset2.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset3.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset4.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset5.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset6.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset7.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset8.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset9.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset10.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset11.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset12.dev_attr.attr, - &sensor_dev_attr_temp1_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_temp2_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_temp3_auto_pwm_min.dev_attr.attr, - &sensor_dev_attr_temp1_auto_offset_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_auto_offset_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_auto_offset_hyst.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan1_smart_tach.dev_attr.attr, - &sensor_dev_attr_fan2_smart_tach.dev_attr.attr, - &sensor_dev_attr_fan3_smart_tach.dev_attr.attr, - &sensor_dev_attr_fan4_smart_tach.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_channels.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_channels.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_spinup_min.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_spinup_min.dev_attr.attr, - &sensor_dev_attr_pwm1_auto_spinup_time.dev_attr.attr, - &sensor_dev_attr_pwm2_auto_spinup_time.dev_attr.attr, - &dev_attr_pwm_auto_prochot_ramp.attr, - &dev_attr_pwm_auto_vrdhot_ramp.attr, - &sensor_dev_attr_cpu0_vid.dev_attr.attr, - &sensor_dev_attr_cpu1_vid.dev_attr.attr, - &sensor_dev_attr_prochot1.dev_attr.attr, - &sensor_dev_attr_prochot2.dev_attr.attr, - &sensor_dev_attr_prochot1_avg.dev_attr.attr, - &sensor_dev_attr_prochot2_avg.dev_attr.attr, - &sensor_dev_attr_prochot1_max.dev_attr.attr, - &sensor_dev_attr_prochot2_max.dev_attr.attr, - &sensor_dev_attr_prochot1_override.dev_attr.attr, - &sensor_dev_attr_prochot2_override.dev_attr.attr, - &sensor_dev_attr_prochot1_interval.dev_attr.attr, - &sensor_dev_attr_prochot2_interval.dev_attr.attr, - &dev_attr_prochot_override_duty_cycle.attr, - &dev_attr_prochot_short.attr, - &sensor_dev_attr_vrdhot1.dev_attr.attr, - &sensor_dev_attr_vrdhot2.dev_attr.attr, - &dev_attr_gpio.attr, - &dev_attr_alarms.attr, - NULL -}; - -static struct attribute_group lm93_attr_grp = { - .attrs = lm93_attrs, -}; - -static void lm93_init_client(struct i2c_client *client) -{ - int i; - u8 reg; - - /* configure VID pin input thresholds */ - reg = lm93_read_byte(client, LM93_REG_GPI_VID_CTL); - lm93_write_byte(client, LM93_REG_GPI_VID_CTL, - reg | (vid_agtl ? 0x03 : 0x00)); - - if (init) { - /* enable #ALERT pin */ - reg = lm93_read_byte(client, LM93_REG_CONFIG); - lm93_write_byte(client, LM93_REG_CONFIG, reg | 0x08); - - /* enable ASF mode for BMC status registers */ - reg = lm93_read_byte(client, LM93_REG_STATUS_CONTROL); - lm93_write_byte(client, LM93_REG_STATUS_CONTROL, reg | 0x02); - - /* set sleep state to S0 */ - lm93_write_byte(client, LM93_REG_SLEEP_CONTROL, 0); - - /* unmask #VRDHOT and dynamic VCCP (if nec) error events */ - reg = lm93_read_byte(client, LM93_REG_MISC_ERR_MASK); - reg &= ~0x03; - reg &= ~(vccp_limit_type[0] ? 0x10 : 0); - reg &= ~(vccp_limit_type[1] ? 0x20 : 0); - lm93_write_byte(client, LM93_REG_MISC_ERR_MASK, reg); - } - - /* start monitoring */ - reg = lm93_read_byte(client, LM93_REG_CONFIG); - lm93_write_byte(client, LM93_REG_CONFIG, reg | 0x01); - - /* spin until ready */ - for (i = 0; i < 20; i++) { - msleep(10); - if ((lm93_read_byte(client, LM93_REG_CONFIG) & 0x80) == 0x80) - return; - } - - dev_warn(&client->dev, "timed out waiting for sensor " - "chip to signal ready!\n"); -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int mfr, ver; - const char *name; - - if (!i2c_check_functionality(adapter, LM93_SMBUS_FUNC_MIN)) - return -ENODEV; - - /* detection */ - mfr = lm93_read_byte(client, LM93_REG_MFR_ID); - if (mfr != 0x01) { - dev_dbg(&adapter->dev, - "detect failed, bad manufacturer id 0x%02x!\n", mfr); - return -ENODEV; - } - - ver = lm93_read_byte(client, LM93_REG_VER); - switch (ver) { - case LM93_MFR_ID: - case LM93_MFR_ID_PROTOTYPE: - name = "lm93"; - break; - case LM94_MFR_ID_2: - case LM94_MFR_ID: - case LM94_MFR_ID_PROTOTYPE: - name = "lm94"; - break; - default: - dev_dbg(&adapter->dev, - "detect failed, bad version id 0x%02x!\n", ver); - return -ENODEV; - } - - strlcpy(info->type, name, I2C_NAME_SIZE); - dev_dbg(&adapter->dev, "loading %s at %d, 0x%02x\n", - client->name, i2c_adapter_id(client->adapter), - client->addr); - - return 0; -} - -static int lm93_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct lm93_data *data; - int err, func; - void (*update)(struct lm93_data *, struct i2c_client *); - - /* choose update routine based on bus capabilities */ - func = i2c_get_functionality(client->adapter); - if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) && - (!disable_block)) { - dev_dbg(&client->dev, "using SMBus block data transactions\n"); - update = lm93_update_client_full; - } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) { - dev_dbg(&client->dev, "disabled SMBus block data " - "transactions\n"); - update = lm93_update_client_min; - } else { - dev_dbg(&client->dev, "detect failed, " - "smbus byte and/or word data not supported!\n"); - err = -ENODEV; - goto err_out; - } - - data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL); - if (!data) { - dev_dbg(&client->dev, "out of memory!\n"); - err = -ENOMEM; - goto err_out; - } - i2c_set_clientdata(client, data); - - /* housekeeping */ - data->valid = 0; - data->update = update; - mutex_init(&data->update_lock); - - /* initialize the chip */ - lm93_init_client(client); - - err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp); - if (err) - goto err_free; - - /* Register hwmon driver class */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; - - err = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "error registering hwmon device.\n"); - sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); -err_free: - kfree(data); -err_out: - return err; -} - -static int lm93_remove(struct i2c_client *client) -{ - struct lm93_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); - - kfree(data); - return 0; -} - -static const struct i2c_device_id lm93_id[] = { - { "lm93", 0 }, - { "lm94", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm93_id); - -static struct i2c_driver lm93_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm93", - }, - .probe = lm93_probe, - .remove = lm93_remove, - .id_table = lm93_id, - .detect = lm93_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm93_driver); - -MODULE_AUTHOR("Mark M. Hoffman , " - "Hans J. Koch "); -MODULE_DESCRIPTION("LM93 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm95241.c b/ANDROID_3.4.5/drivers/hwmon/lm95241.c deleted file mode 100644 index bd8cdb7b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm95241.c +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Copyright (C) 2008, 2010 Davide Rizzo - * - * The LM95241 is a sensor chip made by National Semiconductors. - * It reports up to three temperatures (its own plus up to two external ones). - * Complete datasheet can be obtained from National's website at: - * http://www.national.com/ds.cgi/LM/LM95241.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEVNAME "lm95241" - -static const unsigned short normal_i2c[] = { - 0x19, 0x2a, 0x2b, I2C_CLIENT_END }; - -/* LM95241 registers */ -#define LM95241_REG_R_MAN_ID 0xFE -#define LM95241_REG_R_CHIP_ID 0xFF -#define LM95241_REG_R_STATUS 0x02 -#define LM95241_REG_RW_CONFIG 0x03 -#define LM95241_REG_RW_REM_FILTER 0x06 -#define LM95241_REG_RW_TRUTHERM 0x07 -#define LM95241_REG_W_ONE_SHOT 0x0F -#define LM95241_REG_R_LOCAL_TEMPH 0x10 -#define LM95241_REG_R_REMOTE1_TEMPH 0x11 -#define LM95241_REG_R_REMOTE2_TEMPH 0x12 -#define LM95241_REG_R_LOCAL_TEMPL 0x20 -#define LM95241_REG_R_REMOTE1_TEMPL 0x21 -#define LM95241_REG_R_REMOTE2_TEMPL 0x22 -#define LM95241_REG_RW_REMOTE_MODEL 0x30 - -/* LM95241 specific bitfields */ -#define CFG_STOP 0x40 -#define CFG_CR0076 0x00 -#define CFG_CR0182 0x10 -#define CFG_CR1000 0x20 -#define CFG_CR2700 0x30 -#define R1MS_SHIFT 0 -#define R2MS_SHIFT 2 -#define R1MS_MASK (0x01 << (R1MS_SHIFT)) -#define R2MS_MASK (0x01 << (R2MS_SHIFT)) -#define R1DF_SHIFT 1 -#define R2DF_SHIFT 2 -#define R1DF_MASK (0x01 << (R1DF_SHIFT)) -#define R2DF_MASK (0x01 << (R2DF_SHIFT)) -#define R1FE_MASK 0x01 -#define R2FE_MASK 0x05 -#define TT1_SHIFT 0 -#define TT2_SHIFT 4 -#define TT_OFF 0 -#define TT_ON 1 -#define TT_MASK 7 -#define NATSEMI_MAN_ID 0x01 -#define LM95231_CHIP_ID 0xA1 -#define LM95241_CHIP_ID 0xA4 - -static const u8 lm95241_reg_address[] = { - LM95241_REG_R_LOCAL_TEMPH, - LM95241_REG_R_LOCAL_TEMPL, - LM95241_REG_R_REMOTE1_TEMPH, - LM95241_REG_R_REMOTE1_TEMPL, - LM95241_REG_R_REMOTE2_TEMPH, - LM95241_REG_R_REMOTE2_TEMPL -}; - -/* Client data (each client gets its own) */ -struct lm95241_data { - struct device *hwmon_dev; - struct mutex update_lock; - unsigned long last_updated, interval; /* in jiffies */ - char valid; /* zero until following fields are valid */ - /* registers values */ - u8 temp[ARRAY_SIZE(lm95241_reg_address)]; - u8 config, model, trutherm; -}; - -/* Conversions */ -static int temp_from_reg_signed(u8 val_h, u8 val_l) -{ - s16 val_hl = (val_h << 8) | val_l; - return val_hl * 1000 / 256; -} - -static int temp_from_reg_unsigned(u8 val_h, u8 val_l) -{ - u16 val_hl = (val_h << 8) | val_l; - return val_hl * 1000 / 256; -} - -static struct lm95241_data *lm95241_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + data->interval) || - !data->valid) { - int i; - - dev_dbg(&client->dev, "Updating lm95241 data.\n"); - for (i = 0; i < ARRAY_SIZE(lm95241_reg_address); i++) - data->temp[i] - = i2c_smbus_read_byte_data(client, - lm95241_reg_address[i]); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* Sysfs stuff */ -static ssize_t show_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm95241_data *data = lm95241_update_device(dev); - int index = to_sensor_dev_attr(attr)->index; - - return snprintf(buf, PAGE_SIZE - 1, "%d\n", - index == 0 || (data->config & (1 << (index / 2))) ? - temp_from_reg_signed(data->temp[index], data->temp[index + 1]) : - temp_from_reg_unsigned(data->temp[index], - data->temp[index + 1])); -} - -static ssize_t show_type(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - - return snprintf(buf, PAGE_SIZE - 1, - data->model & to_sensor_dev_attr(attr)->index ? "1\n" : "2\n"); -} - -static ssize_t set_type(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - unsigned long val; - int shift; - u8 mask = to_sensor_dev_attr(attr)->index; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - if (val != 1 && val != 2) - return -EINVAL; - - shift = mask == R1MS_MASK ? TT1_SHIFT : TT2_SHIFT; - - mutex_lock(&data->update_lock); - - data->trutherm &= ~(TT_MASK << shift); - if (val == 1) { - data->model |= mask; - data->trutherm |= (TT_ON << shift); - } else { - data->model &= ~mask; - data->trutherm |= (TT_OFF << shift); - } - data->valid = 0; - - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, - data->model); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, - data->trutherm); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - - return snprintf(buf, PAGE_SIZE - 1, - data->config & to_sensor_dev_attr(attr)->index ? - "-127000\n" : "0\n"); -} - -static ssize_t set_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - long val; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - if (val < -128000) - return -EINVAL; - - mutex_lock(&data->update_lock); - - if (val < 0) - data->config |= to_sensor_dev_attr(attr)->index; - else - data->config &= ~to_sensor_dev_attr(attr)->index; - data->valid = 0; - - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - - return snprintf(buf, PAGE_SIZE - 1, - data->config & to_sensor_dev_attr(attr)->index ? - "127000\n" : "255000\n"); -} - -static ssize_t set_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - long val; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - if (val >= 256000) - return -EINVAL; - - mutex_lock(&data->update_lock); - - if (val <= 127000) - data->config |= to_sensor_dev_attr(attr)->index; - else - data->config &= ~to_sensor_dev_attr(attr)->index; - data->valid = 0; - - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_interval(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm95241_data *data = lm95241_update_device(dev); - - return snprintf(buf, PAGE_SIZE - 1, "%lu\n", 1000 * data->interval - / HZ); -} - -static ssize_t set_interval(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95241_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - data->interval = val * HZ / 1000; - - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_input, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, set_type, - R1MS_MASK); -static SENSOR_DEVICE_ATTR(temp3_type, S_IWUSR | S_IRUGO, show_type, set_type, - R2MS_MASK); -static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_min, set_min, - R1DF_MASK); -static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO, show_min, set_min, - R2DF_MASK); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_max, set_max, - R1DF_MASK); -static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO, show_max, set_max, - R2DF_MASK); -static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, - set_interval); - -static struct attribute *lm95241_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp2_type.dev_attr.attr, - &sensor_dev_attr_temp3_type.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &dev_attr_update_interval.attr, - NULL -}; - -static const struct attribute_group lm95241_group = { - .attrs = lm95241_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm95241_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - const char *name; - int mfg_id, chip_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - mfg_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_MAN_ID); - if (mfg_id != NATSEMI_MAN_ID) - return -ENODEV; - - chip_id = i2c_smbus_read_byte_data(new_client, LM95241_REG_R_CHIP_ID); - switch (chip_id) { - case LM95231_CHIP_ID: - name = "lm95231"; - break; - case LM95241_CHIP_ID: - name = "lm95241"; - break; - default: - return -ENODEV; - } - - /* Fill the i2c board info */ - strlcpy(info->type, name, I2C_NAME_SIZE); - return 0; -} - -static void lm95241_init_client(struct i2c_client *client) -{ - struct lm95241_data *data = i2c_get_clientdata(client); - - data->interval = HZ; /* 1 sec default */ - data->valid = 0; - data->config = CFG_CR0076; - data->model = 0; - data->trutherm = (TT_OFF << TT1_SHIFT) | (TT_OFF << TT2_SHIFT); - - i2c_smbus_write_byte_data(client, LM95241_REG_RW_CONFIG, data->config); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REM_FILTER, - R1FE_MASK | R2FE_MASK); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_TRUTHERM, - data->trutherm); - i2c_smbus_write_byte_data(client, LM95241_REG_RW_REMOTE_MODEL, - data->model); -} - -static int lm95241_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm95241_data *data; - int err; - - data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - mutex_init(&data->update_lock); - - /* Initialize the LM95241 chip */ - lm95241_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int lm95241_remove(struct i2c_client *client) -{ - struct lm95241_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm95241_group); - - kfree(data); - return 0; -} - -/* Driver data (common to all clients) */ -static const struct i2c_device_id lm95241_id[] = { - { "lm95231", 0 }, - { "lm95241", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm95241_id); - -static struct i2c_driver lm95241_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = DEVNAME, - }, - .probe = lm95241_probe, - .remove = lm95241_remove, - .id_table = lm95241_id, - .detect = lm95241_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm95241_driver); - -MODULE_AUTHOR("Davide Rizzo "); -MODULE_DESCRIPTION("LM95241 sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/lm95245.c b/ANDROID_3.4.5/drivers/hwmon/lm95245.c deleted file mode 100644 index 9a46c106..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/lm95245.c +++ /dev/null @@ -1,532 +0,0 @@ -/* - * Copyright (C) 2011 Alexander Stein - * - * The LM95245 is a sensor chip made by National Semiconductors. - * It reports up to two temperatures (its own plus an external one). - * Complete datasheet can be obtained from National's website at: - * http://www.national.com/ds.cgi/LM/LM95245.pdf - * - * This driver is based on lm95241.c - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DEVNAME "lm95245" - -static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END }; - -/* LM95245 registers */ -/* general registers */ -#define LM95245_REG_RW_CONFIG1 0x03 -#define LM95245_REG_RW_CONVERS_RATE 0x04 -#define LM95245_REG_W_ONE_SHOT 0x0F - -/* diode configuration */ -#define LM95245_REG_RW_CONFIG2 0xBF -#define LM95245_REG_RW_REMOTE_OFFH 0x11 -#define LM95245_REG_RW_REMOTE_OFFL 0x12 - -/* status registers */ -#define LM95245_REG_R_STATUS1 0x02 -#define LM95245_REG_R_STATUS2 0x33 - -/* limit registers */ -#define LM95245_REG_RW_REMOTE_OS_LIMIT 0x07 -#define LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT 0x20 -#define LM95245_REG_RW_REMOTE_TCRIT_LIMIT 0x19 -#define LM95245_REG_RW_COMMON_HYSTERESIS 0x21 - -/* temperature signed */ -#define LM95245_REG_R_LOCAL_TEMPH_S 0x00 -#define LM95245_REG_R_LOCAL_TEMPL_S 0x30 -#define LM95245_REG_R_REMOTE_TEMPH_S 0x01 -#define LM95245_REG_R_REMOTE_TEMPL_S 0x10 -/* temperature unsigned */ -#define LM95245_REG_R_REMOTE_TEMPH_U 0x31 -#define LM95245_REG_R_REMOTE_TEMPL_U 0x32 - -/* id registers */ -#define LM95245_REG_R_MAN_ID 0xFE -#define LM95245_REG_R_CHIP_ID 0xFF - -/* LM95245 specific bitfields */ -#define CFG_STOP 0x40 -#define CFG_REMOTE_TCRIT_MASK 0x10 -#define CFG_REMOTE_OS_MASK 0x08 -#define CFG_LOCAL_TCRIT_MASK 0x04 -#define CFG_LOCAL_OS_MASK 0x02 - -#define CFG2_OS_A0 0x40 -#define CFG2_DIODE_FAULT_OS 0x20 -#define CFG2_DIODE_FAULT_TCRIT 0x10 -#define CFG2_REMOTE_TT 0x08 -#define CFG2_REMOTE_FILTER_DIS 0x00 -#define CFG2_REMOTE_FILTER_EN 0x06 - -/* conversation rate in ms */ -#define RATE_CR0063 0x00 -#define RATE_CR0364 0x01 -#define RATE_CR1000 0x02 -#define RATE_CR2500 0x03 - -#define STATUS1_DIODE_FAULT 0x04 -#define STATUS1_RTCRIT 0x02 -#define STATUS1_LOC 0x01 - -#define MANUFACTURER_ID 0x01 -#define DEFAULT_REVISION 0xB3 - -static const u8 lm95245_reg_address[] = { - LM95245_REG_R_LOCAL_TEMPH_S, - LM95245_REG_R_LOCAL_TEMPL_S, - LM95245_REG_R_REMOTE_TEMPH_S, - LM95245_REG_R_REMOTE_TEMPL_S, - LM95245_REG_R_REMOTE_TEMPH_U, - LM95245_REG_R_REMOTE_TEMPL_U, - LM95245_REG_RW_LOCAL_OS_TCRIT_LIMIT, - LM95245_REG_RW_REMOTE_TCRIT_LIMIT, - LM95245_REG_RW_COMMON_HYSTERESIS, - LM95245_REG_R_STATUS1, -}; - -/* Client data (each client gets its own) */ -struct lm95245_data { - struct device *hwmon_dev; - struct mutex update_lock; - unsigned long last_updated; /* in jiffies */ - unsigned long interval; /* in msecs */ - bool valid; /* zero until following fields are valid */ - /* registers values */ - u8 regs[ARRAY_SIZE(lm95245_reg_address)]; - u8 config1, config2; -}; - -/* Conversions */ -static int temp_from_reg_unsigned(u8 val_h, u8 val_l) -{ - return val_h * 1000 + val_l * 1000 / 256; -} - -static int temp_from_reg_signed(u8 val_h, u8 val_l) -{ - if (val_h & 0x80) - return (val_h - 0x100) * 1000; - return temp_from_reg_unsigned(val_h, val_l); -} - -static struct lm95245_data *lm95245_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95245_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated - + msecs_to_jiffies(data->interval)) || !data->valid) { - int i; - - dev_dbg(&client->dev, "Updating lm95245 data.\n"); - for (i = 0; i < ARRAY_SIZE(lm95245_reg_address); i++) - data->regs[i] - = i2c_smbus_read_byte_data(client, - lm95245_reg_address[i]); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static unsigned long lm95245_read_conversion_rate(struct i2c_client *client) -{ - int rate; - unsigned long interval; - - rate = i2c_smbus_read_byte_data(client, LM95245_REG_RW_CONVERS_RATE); - - switch (rate) { - case RATE_CR0063: - interval = 63; - break; - case RATE_CR0364: - interval = 364; - break; - case RATE_CR1000: - interval = 1000; - break; - case RATE_CR2500: - default: - interval = 2500; - break; - } - - return interval; -} - -static unsigned long lm95245_set_conversion_rate(struct i2c_client *client, - unsigned long interval) -{ - int rate; - - if (interval <= 63) { - interval = 63; - rate = RATE_CR0063; - } else if (interval <= 364) { - interval = 364; - rate = RATE_CR0364; - } else if (interval <= 1000) { - interval = 1000; - rate = RATE_CR1000; - } else { - interval = 2500; - rate = RATE_CR2500; - } - - i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONVERS_RATE, rate); - - return interval; -} - -/* Sysfs stuff */ -static ssize_t show_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm95245_data *data = lm95245_update_device(dev); - int temp; - int index = to_sensor_dev_attr(attr)->index; - - /* - * Index 0 (Local temp) is always signed - * Index 2 (Remote temp) has both signed and unsigned data - * use signed calculation for remote if signed bit is set - */ - if (index == 0 || data->regs[index] & 0x80) - temp = temp_from_reg_signed(data->regs[index], - data->regs[index + 1]); - else - temp = temp_from_reg_unsigned(data->regs[index + 2], - data->regs[index + 3]); - - return snprintf(buf, PAGE_SIZE - 1, "%d\n", temp); -} - -static ssize_t show_limit(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm95245_data *data = lm95245_update_device(dev); - int index = to_sensor_dev_attr(attr)->index; - - return snprintf(buf, PAGE_SIZE - 1, "%d\n", - data->regs[index] * 1000); -} - -static ssize_t set_limit(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95245_data *data = i2c_get_clientdata(client); - int index = to_sensor_dev_attr(attr)->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - val /= 1000; - - val = SENSORS_LIMIT(val, 0, (index == 6 ? 127 : 255)); - - mutex_lock(&data->update_lock); - - data->valid = 0; - - i2c_smbus_write_byte_data(client, lm95245_reg_address[index], val); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_crit_hyst(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95245_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - val /= 1000; - - val = SENSORS_LIMIT(val, 0, 31); - - mutex_lock(&data->update_lock); - - data->valid = 0; - - /* shared crit hysteresis */ - i2c_smbus_write_byte_data(client, LM95245_REG_RW_COMMON_HYSTERESIS, - val); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_type(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95245_data *data = i2c_get_clientdata(client); - - return snprintf(buf, PAGE_SIZE - 1, - data->config2 & CFG2_REMOTE_TT ? "1\n" : "2\n"); -} - -static ssize_t set_type(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95245_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - if (val != 1 && val != 2) - return -EINVAL; - - mutex_lock(&data->update_lock); - - if (val == 1) - data->config2 |= CFG2_REMOTE_TT; - else - data->config2 &= ~CFG2_REMOTE_TT; - - data->valid = 0; - - i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG2, - data->config2); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm95245_data *data = lm95245_update_device(dev); - int index = to_sensor_dev_attr(attr)->index; - - return snprintf(buf, PAGE_SIZE - 1, "%d\n", - !!(data->regs[9] & index)); -} - -static ssize_t show_interval(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct lm95245_data *data = lm95245_update_device(dev); - - return snprintf(buf, PAGE_SIZE - 1, "%lu\n", data->interval); -} - -static ssize_t set_interval(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm95245_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - - data->interval = lm95245_set_conversion_rate(client, val); - - mutex_unlock(&data->update_lock); - - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_limit, - set_limit, 6); -static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_limit, - set_crit_hyst, 8); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, - STATUS1_LOC); - -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_input, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_limit, - set_limit, 7); -static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_limit, - set_crit_hyst, 8); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, - STATUS1_RTCRIT); -static SENSOR_DEVICE_ATTR(temp2_type, S_IWUSR | S_IRUGO, show_type, - set_type, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, - STATUS1_DIODE_FAULT); - -static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, - set_interval); - -static struct attribute *lm95245_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_type.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &dev_attr_update_interval.attr, - NULL -}; - -static const struct attribute_group lm95245_group = { - .attrs = lm95245_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int lm95245_detect(struct i2c_client *new_client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = new_client->adapter; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - if (i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID) - != MANUFACTURER_ID - || i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID) - != DEFAULT_REVISION) - return -ENODEV; - - strlcpy(info->type, DEVNAME, I2C_NAME_SIZE); - return 0; -} - -static void lm95245_init_client(struct i2c_client *client) -{ - struct lm95245_data *data = i2c_get_clientdata(client); - - data->valid = 0; - data->interval = lm95245_read_conversion_rate(client); - - data->config1 = i2c_smbus_read_byte_data(client, - LM95245_REG_RW_CONFIG1); - data->config2 = i2c_smbus_read_byte_data(client, - LM95245_REG_RW_CONFIG2); - - if (data->config1 & CFG_STOP) { - /* Clear the standby bit */ - data->config1 &= ~CFG_STOP; - i2c_smbus_write_byte_data(client, LM95245_REG_RW_CONFIG1, - data->config1); - } -} - -static int lm95245_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct lm95245_data *data; - int err; - - data = kzalloc(sizeof(struct lm95245_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - mutex_init(&data->update_lock); - - /* Initialize the LM95245 chip */ - lm95245_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &lm95245_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int lm95245_remove(struct i2c_client *client) -{ - struct lm95245_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm95245_group); - - kfree(data); - return 0; -} - -/* Driver data (common to all clients) */ -static const struct i2c_device_id lm95245_id[] = { - { DEVNAME, 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm95245_id); - -static struct i2c_driver lm95245_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = DEVNAME, - }, - .probe = lm95245_probe, - .remove = lm95245_remove, - .id_table = lm95245_id, - .detect = lm95245_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(lm95245_driver); - -MODULE_AUTHOR("Alexander Stein "); -MODULE_DESCRIPTION("LM95245 sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ltc4151.c b/ANDROID_3.4.5/drivers/hwmon/ltc4151.c deleted file mode 100644 index 4d005b21..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ltc4151.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Driver for Linear Technology LTC4151 High Voltage I2C Current - * and Voltage Monitor - * - * Copyright (C) 2011 AppearTV AS - * - * Derived from: - * - * Driver for Linear Technology LTC4261 I2C Negative Voltage Hot - * Swap Controller - * Copyright (C) 2010 Ericsson AB. - * - * Datasheet: http://www.linear.com/docs/Datasheet/4151fc.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* chip registers */ -#define LTC4151_SENSE_H 0x00 -#define LTC4151_SENSE_L 0x01 -#define LTC4151_VIN_H 0x02 -#define LTC4151_VIN_L 0x03 -#define LTC4151_ADIN_H 0x04 -#define LTC4151_ADIN_L 0x05 - -struct ltc4151_data { - struct device *hwmon_dev; - - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - - /* Registers */ - u8 regs[6]; -}; - -static struct ltc4151_data *ltc4151_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ltc4151_data *data = i2c_get_clientdata(client); - struct ltc4151_data *ret = data; - - mutex_lock(&data->update_lock); - - /* - * The chip's A/D updates 6 times per second - * (Conversion Rate 6 - 9 Hz) - */ - if (time_after(jiffies, data->last_updated + HZ / 6) || !data->valid) { - int i; - - dev_dbg(&client->dev, "Starting ltc4151 update\n"); - - /* Read all registers */ - for (i = 0; i < ARRAY_SIZE(data->regs); i++) { - int val; - - val = i2c_smbus_read_byte_data(client, i); - if (unlikely(val < 0)) { - dev_dbg(dev, - "Failed to read ADC value: error %d\n", - val); - ret = ERR_PTR(val); - goto abort; - } - data->regs[i] = val; - } - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -/* Return the voltage from the given register in mV */ -static int ltc4151_get_value(struct ltc4151_data *data, u8 reg) -{ - u32 val; - - val = (data->regs[reg] << 4) + (data->regs[reg + 1] >> 4); - - switch (reg) { - case LTC4151_ADIN_H: - /* 500uV resolution. Convert to mV. */ - val = val * 500 / 1000; - break; - case LTC4151_SENSE_H: - /* - * 20uV resolution. Convert to current as measured with - * an 1 mOhm sense resistor, in mA. - */ - val = val * 20; - break; - case LTC4151_VIN_H: - /* 25 mV per increment */ - val = val * 25; - break; - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - val = 0; - break; - } - - return val; -} - -static ssize_t ltc4151_show_value(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ltc4151_data *data = ltc4151_update_device(dev); - int value; - - if (IS_ERR(data)) - return PTR_ERR(data); - - value = ltc4151_get_value(data, attr->index); - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -/* - * Input voltages. - */ -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \ - ltc4151_show_value, NULL, LTC4151_VIN_H); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, \ - ltc4151_show_value, NULL, LTC4151_ADIN_H); - -/* Currents (via sense resistor) */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \ - ltc4151_show_value, NULL, LTC4151_SENSE_H); - -/* - * Finally, construct an array of pointers to members of the above objects, - * as required for sysfs_create_group() - */ -static struct attribute *ltc4151_attributes[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - - &sensor_dev_attr_curr1_input.dev_attr.attr, - - NULL, -}; - -static const struct attribute_group ltc4151_group = { - .attrs = ltc4151_attributes, -}; - -static int ltc4151_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct ltc4151_data *data; - int ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto out_kzalloc; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, <c4151_group); - if (ret) - goto out_sysfs_create_group; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_hwmon_device_register; - } - - return 0; - -out_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, <c4151_group); -out_sysfs_create_group: - kfree(data); -out_kzalloc: - return ret; -} - -static int ltc4151_remove(struct i2c_client *client) -{ - struct ltc4151_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, <c4151_group); - - kfree(data); - - return 0; -} - -static const struct i2c_device_id ltc4151_id[] = { - { "ltc4151", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ltc4151_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ltc4151_driver = { - .driver = { - .name = "ltc4151", - }, - .probe = ltc4151_probe, - .remove = ltc4151_remove, - .id_table = ltc4151_id, -}; - -module_i2c_driver(ltc4151_driver); - -MODULE_AUTHOR("Per Dalen "); -MODULE_DESCRIPTION("LTC4151 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ltc4215.c b/ANDROID_3.4.5/drivers/hwmon/ltc4215.c deleted file mode 100644 index 429c5b2b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ltc4215.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Driver for Linear Technology LTC4215 I2C Hot Swap Controller - * - * Copyright (C) 2009 Ira W. Snyder - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * Datasheet: - * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1163,P17572,D12697 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* Here are names of the chip's registers (a.k.a. commands) */ -enum ltc4215_cmd { - LTC4215_CONTROL = 0x00, /* rw */ - LTC4215_ALERT = 0x01, /* rw */ - LTC4215_STATUS = 0x02, /* ro */ - LTC4215_FAULT = 0x03, /* rw */ - LTC4215_SENSE = 0x04, /* rw */ - LTC4215_SOURCE = 0x05, /* rw */ - LTC4215_ADIN = 0x06, /* rw */ -}; - -struct ltc4215_data { - struct device *hwmon_dev; - - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - - /* Registers */ - u8 regs[7]; -}; - -static struct ltc4215_data *ltc4215_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ltc4215_data *data = i2c_get_clientdata(client); - s32 val; - int i; - - mutex_lock(&data->update_lock); - - /* The chip's A/D updates 10 times per second */ - if (time_after(jiffies, data->last_updated + HZ / 10) || !data->valid) { - - dev_dbg(&client->dev, "Starting ltc4215 update\n"); - - /* Read all registers */ - for (i = 0; i < ARRAY_SIZE(data->regs); i++) { - val = i2c_smbus_read_byte_data(client, i); - if (unlikely(val < 0)) - data->regs[i] = 0; - else - data->regs[i] = val; - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* Return the voltage from the given register in millivolts */ -static int ltc4215_get_voltage(struct device *dev, u8 reg) -{ - struct ltc4215_data *data = ltc4215_update_device(dev); - const u8 regval = data->regs[reg]; - u32 voltage = 0; - - switch (reg) { - case LTC4215_SENSE: - /* 151 uV per increment */ - voltage = regval * 151 / 1000; - break; - case LTC4215_SOURCE: - /* 60.5 mV per increment */ - voltage = regval * 605 / 10; - break; - case LTC4215_ADIN: - /* - * The ADIN input is divided by 12.5, and has 4.82 mV - * per increment, so we have the additional multiply - */ - voltage = regval * 482 * 125 / 1000; - break; - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - break; - } - - return voltage; -} - -/* Return the current from the sense resistor in mA */ -static unsigned int ltc4215_get_current(struct device *dev) -{ - struct ltc4215_data *data = ltc4215_update_device(dev); - - /* - * The strange looking conversions that follow are fixed-point - * math, since we cannot do floating point in the kernel. - * - * Step 1: convert sense register to microVolts - * Step 2: convert voltage to milliAmperes - * - * If you play around with the V=IR equation, you come up with - * the following: X uV / Y mOhm == Z mA - * - * With the resistors that are fractions of a milliOhm, we multiply - * the voltage and resistance by 10, to shift the decimal point. - * Now we can use the normal division operator again. - */ - - /* Calculate voltage in microVolts (151 uV per increment) */ - const unsigned int voltage = data->regs[LTC4215_SENSE] * 151; - - /* Calculate current in milliAmperes (4 milliOhm sense resistor) */ - const unsigned int curr = voltage / 4; - - return curr; -} - -static ssize_t ltc4215_show_voltage(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - const int voltage = ltc4215_get_voltage(dev, attr->index); - - return snprintf(buf, PAGE_SIZE, "%d\n", voltage); -} - -static ssize_t ltc4215_show_current(struct device *dev, - struct device_attribute *da, - char *buf) -{ - const unsigned int curr = ltc4215_get_current(dev); - - return snprintf(buf, PAGE_SIZE, "%u\n", curr); -} - -static ssize_t ltc4215_show_power(struct device *dev, - struct device_attribute *da, - char *buf) -{ - const unsigned int curr = ltc4215_get_current(dev); - const int output_voltage = ltc4215_get_voltage(dev, LTC4215_ADIN); - - /* current in mA * voltage in mV == power in uW */ - const unsigned int power = abs(output_voltage * curr); - - return snprintf(buf, PAGE_SIZE, "%u\n", power); -} - -static ssize_t ltc4215_show_alarm(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); - struct ltc4215_data *data = ltc4215_update_device(dev); - const u8 reg = data->regs[attr->index]; - const u32 mask = attr->nr; - - return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); -} - -/* - * These macros are used below in constructing device attribute objects - * for use with sysfs_create_group() to make a sysfs device file - * for each register. - */ - -#define LTC4215_VOLTAGE(name, ltc4215_cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4215_show_voltage, NULL, ltc4215_cmd_idx) - -#define LTC4215_CURRENT(name) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4215_show_current, NULL, 0); - -#define LTC4215_POWER(name) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4215_show_power, NULL, 0); - -#define LTC4215_ALARM(name, mask, reg) \ - static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ - ltc4215_show_alarm, NULL, (mask), reg) - -/* Construct a sensor_device_attribute structure for each register */ - -/* Current */ -LTC4215_CURRENT(curr1_input); -LTC4215_ALARM(curr1_max_alarm, (1 << 2), LTC4215_STATUS); - -/* Power (virtual) */ -LTC4215_POWER(power1_input); - -/* Input Voltage */ -LTC4215_VOLTAGE(in1_input, LTC4215_ADIN); -LTC4215_ALARM(in1_max_alarm, (1 << 0), LTC4215_STATUS); -LTC4215_ALARM(in1_min_alarm, (1 << 1), LTC4215_STATUS); - -/* Output Voltage */ -LTC4215_VOLTAGE(in2_input, LTC4215_SOURCE); -LTC4215_ALARM(in2_min_alarm, (1 << 3), LTC4215_STATUS); - -/* - * Finally, construct an array of pointers to members of the above objects, - * as required for sysfs_create_group() - */ -static struct attribute *ltc4215_attributes[] = { - &sensor_dev_attr_curr1_input.dev_attr.attr, - &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, - - &sensor_dev_attr_power1_input.dev_attr.attr, - - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max_alarm.dev_attr.attr, - &sensor_dev_attr_in1_min_alarm.dev_attr.attr, - - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_min_alarm.dev_attr.attr, - - NULL, -}; - -static const struct attribute_group ltc4215_group = { - .attrs = ltc4215_attributes, -}; - -static int ltc4215_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct ltc4215_data *data; - int ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto out_kzalloc; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the LTC4215 chip */ - i2c_smbus_write_byte_data(client, LTC4215_FAULT, 0x00); - - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, <c4215_group); - if (ret) - goto out_sysfs_create_group; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_hwmon_device_register; - } - - return 0; - -out_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, <c4215_group); -out_sysfs_create_group: - kfree(data); -out_kzalloc: - return ret; -} - -static int ltc4215_remove(struct i2c_client *client) -{ - struct ltc4215_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, <c4215_group); - - kfree(data); - - return 0; -} - -static const struct i2c_device_id ltc4215_id[] = { - { "ltc4215", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ltc4215_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ltc4215_driver = { - .driver = { - .name = "ltc4215", - }, - .probe = ltc4215_probe, - .remove = ltc4215_remove, - .id_table = ltc4215_id, -}; - -module_i2c_driver(ltc4215_driver); - -MODULE_AUTHOR("Ira W. Snyder "); -MODULE_DESCRIPTION("LTC4215 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ltc4245.c b/ANDROID_3.4.5/drivers/hwmon/ltc4245.c deleted file mode 100644 index b99b45ba..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ltc4245.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller - * - * Copyright (C) 2008 Ira W. Snyder - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This driver is based on the ds1621 and ina209 drivers. - * - * Datasheet: - * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Here are names of the chip's registers (a.k.a. commands) */ -enum ltc4245_cmd { - LTC4245_STATUS = 0x00, /* readonly */ - LTC4245_ALERT = 0x01, - LTC4245_CONTROL = 0x02, - LTC4245_ON = 0x03, - LTC4245_FAULT1 = 0x04, - LTC4245_FAULT2 = 0x05, - LTC4245_GPIO = 0x06, - LTC4245_ADCADR = 0x07, - - LTC4245_12VIN = 0x10, - LTC4245_12VSENSE = 0x11, - LTC4245_12VOUT = 0x12, - LTC4245_5VIN = 0x13, - LTC4245_5VSENSE = 0x14, - LTC4245_5VOUT = 0x15, - LTC4245_3VIN = 0x16, - LTC4245_3VSENSE = 0x17, - LTC4245_3VOUT = 0x18, - LTC4245_VEEIN = 0x19, - LTC4245_VEESENSE = 0x1a, - LTC4245_VEEOUT = 0x1b, - LTC4245_GPIOADC = 0x1c, -}; - -struct ltc4245_data { - struct device *hwmon_dev; - - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - - /* Control registers */ - u8 cregs[0x08]; - - /* Voltage registers */ - u8 vregs[0x0d]; - - /* GPIO ADC registers */ - bool use_extra_gpios; - int gpios[3]; -}; - -/* - * Update the readings from the GPIO pins. If the driver has been configured to - * sample all GPIO's as analog voltages, a round-robin sampling method is used. - * Otherwise, only the configured GPIO pin is sampled. - * - * LOCKING: must hold data->update_lock - */ -static void ltc4245_update_gpios(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ltc4245_data *data = i2c_get_clientdata(client); - u8 gpio_curr, gpio_next, gpio_reg; - int i; - - /* no extra gpio support, we're basically done */ - if (!data->use_extra_gpios) { - data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10]; - return; - } - - /* - * If the last reading was too long ago, then we mark all old GPIO - * readings as stale by setting them to -EAGAIN - */ - if (time_after(jiffies, data->last_updated + 5 * HZ)) { - dev_dbg(&client->dev, "Marking GPIOs invalid\n"); - for (i = 0; i < ARRAY_SIZE(data->gpios); i++) - data->gpios[i] = -EAGAIN; - } - - /* - * Get the current GPIO pin - * - * The datasheet calls these GPIO[1-3], but we'll calculate the zero - * based array index instead, and call them GPIO[0-2]. This is much - * easier to think about. - */ - gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6; - if (gpio_curr > 0) - gpio_curr -= 1; - - /* Read the GPIO voltage from the GPIOADC register */ - data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10]; - - /* Find the next GPIO pin to read */ - gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios); - - /* - * Calculate the correct setting for the GPIO register so it will - * sample the next GPIO pin - */ - gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6); - - /* Update the GPIO register */ - i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg); - - /* Update saved data */ - data->cregs[LTC4245_GPIO] = gpio_reg; -} - -static struct ltc4245_data *ltc4245_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ltc4245_data *data = i2c_get_clientdata(client); - s32 val; - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - - dev_dbg(&client->dev, "Starting ltc4245 update\n"); - - /* Read control registers -- 0x00 to 0x07 */ - for (i = 0; i < ARRAY_SIZE(data->cregs); i++) { - val = i2c_smbus_read_byte_data(client, i); - if (unlikely(val < 0)) - data->cregs[i] = 0; - else - data->cregs[i] = val; - } - - /* Read voltage registers -- 0x10 to 0x1c */ - for (i = 0; i < ARRAY_SIZE(data->vregs); i++) { - val = i2c_smbus_read_byte_data(client, i+0x10); - if (unlikely(val < 0)) - data->vregs[i] = 0; - else - data->vregs[i] = val; - } - - /* Update GPIO readings */ - ltc4245_update_gpios(dev); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* Return the voltage from the given register in millivolts */ -static int ltc4245_get_voltage(struct device *dev, u8 reg) -{ - struct ltc4245_data *data = ltc4245_update_device(dev); - const u8 regval = data->vregs[reg - 0x10]; - u32 voltage = 0; - - switch (reg) { - case LTC4245_12VIN: - case LTC4245_12VOUT: - voltage = regval * 55; - break; - case LTC4245_5VIN: - case LTC4245_5VOUT: - voltage = regval * 22; - break; - case LTC4245_3VIN: - case LTC4245_3VOUT: - voltage = regval * 15; - break; - case LTC4245_VEEIN: - case LTC4245_VEEOUT: - voltage = regval * -55; - break; - case LTC4245_GPIOADC: - voltage = regval * 10; - break; - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - break; - } - - return voltage; -} - -/* Return the current in the given sense register in milliAmperes */ -static unsigned int ltc4245_get_current(struct device *dev, u8 reg) -{ - struct ltc4245_data *data = ltc4245_update_device(dev); - const u8 regval = data->vregs[reg - 0x10]; - unsigned int voltage; - unsigned int curr; - - /* - * The strange looking conversions that follow are fixed-point - * math, since we cannot do floating point in the kernel. - * - * Step 1: convert sense register to microVolts - * Step 2: convert voltage to milliAmperes - * - * If you play around with the V=IR equation, you come up with - * the following: X uV / Y mOhm == Z mA - * - * With the resistors that are fractions of a milliOhm, we multiply - * the voltage and resistance by 10, to shift the decimal point. - * Now we can use the normal division operator again. - */ - - switch (reg) { - case LTC4245_12VSENSE: - voltage = regval * 250; /* voltage in uV */ - curr = voltage / 50; /* sense resistor 50 mOhm */ - break; - case LTC4245_5VSENSE: - voltage = regval * 125; /* voltage in uV */ - curr = (voltage * 10) / 35; /* sense resistor 3.5 mOhm */ - break; - case LTC4245_3VSENSE: - voltage = regval * 125; /* voltage in uV */ - curr = (voltage * 10) / 25; /* sense resistor 2.5 mOhm */ - break; - case LTC4245_VEESENSE: - voltage = regval * 250; /* voltage in uV */ - curr = voltage / 100; /* sense resistor 100 mOhm */ - break; - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - curr = 0; - break; - } - - return curr; -} - -static ssize_t ltc4245_show_voltage(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - const int voltage = ltc4245_get_voltage(dev, attr->index); - - return snprintf(buf, PAGE_SIZE, "%d\n", voltage); -} - -static ssize_t ltc4245_show_current(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - const unsigned int curr = ltc4245_get_current(dev, attr->index); - - return snprintf(buf, PAGE_SIZE, "%u\n", curr); -} - -static ssize_t ltc4245_show_power(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - const unsigned int curr = ltc4245_get_current(dev, attr->index); - const int output_voltage = ltc4245_get_voltage(dev, attr->index+1); - - /* current in mA * voltage in mV == power in uW */ - const unsigned int power = abs(output_voltage * curr); - - return snprintf(buf, PAGE_SIZE, "%u\n", power); -} - -static ssize_t ltc4245_show_alarm(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da); - struct ltc4245_data *data = ltc4245_update_device(dev); - const u8 reg = data->cregs[attr->index]; - const u32 mask = attr->nr; - - return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0); -} - -static ssize_t ltc4245_show_gpio(struct device *dev, - struct device_attribute *da, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ltc4245_data *data = ltc4245_update_device(dev); - int val = data->gpios[attr->index]; - - /* handle stale GPIO's */ - if (val < 0) - return val; - - /* Convert to millivolts and print */ - return snprintf(buf, PAGE_SIZE, "%u\n", val * 10); -} - -/* - * These macros are used below in constructing device attribute objects - * for use with sysfs_create_group() to make a sysfs device file - * for each register. - */ - -#define LTC4245_VOLTAGE(name, ltc4245_cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4245_show_voltage, NULL, ltc4245_cmd_idx) - -#define LTC4245_CURRENT(name, ltc4245_cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4245_show_current, NULL, ltc4245_cmd_idx) - -#define LTC4245_POWER(name, ltc4245_cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4245_show_power, NULL, ltc4245_cmd_idx) - -#define LTC4245_ALARM(name, mask, reg) \ - static SENSOR_DEVICE_ATTR_2(name, S_IRUGO, \ - ltc4245_show_alarm, NULL, (mask), reg) - -#define LTC4245_GPIO_VOLTAGE(name, gpio_num) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4245_show_gpio, NULL, gpio_num) - -/* Construct a sensor_device_attribute structure for each register */ - -/* Input voltages */ -LTC4245_VOLTAGE(in1_input, LTC4245_12VIN); -LTC4245_VOLTAGE(in2_input, LTC4245_5VIN); -LTC4245_VOLTAGE(in3_input, LTC4245_3VIN); -LTC4245_VOLTAGE(in4_input, LTC4245_VEEIN); - -/* Input undervoltage alarms */ -LTC4245_ALARM(in1_min_alarm, (1 << 0), LTC4245_FAULT1); -LTC4245_ALARM(in2_min_alarm, (1 << 1), LTC4245_FAULT1); -LTC4245_ALARM(in3_min_alarm, (1 << 2), LTC4245_FAULT1); -LTC4245_ALARM(in4_min_alarm, (1 << 3), LTC4245_FAULT1); - -/* Currents (via sense resistor) */ -LTC4245_CURRENT(curr1_input, LTC4245_12VSENSE); -LTC4245_CURRENT(curr2_input, LTC4245_5VSENSE); -LTC4245_CURRENT(curr3_input, LTC4245_3VSENSE); -LTC4245_CURRENT(curr4_input, LTC4245_VEESENSE); - -/* Overcurrent alarms */ -LTC4245_ALARM(curr1_max_alarm, (1 << 4), LTC4245_FAULT1); -LTC4245_ALARM(curr2_max_alarm, (1 << 5), LTC4245_FAULT1); -LTC4245_ALARM(curr3_max_alarm, (1 << 6), LTC4245_FAULT1); -LTC4245_ALARM(curr4_max_alarm, (1 << 7), LTC4245_FAULT1); - -/* Output voltages */ -LTC4245_VOLTAGE(in5_input, LTC4245_12VOUT); -LTC4245_VOLTAGE(in6_input, LTC4245_5VOUT); -LTC4245_VOLTAGE(in7_input, LTC4245_3VOUT); -LTC4245_VOLTAGE(in8_input, LTC4245_VEEOUT); - -/* Power Bad alarms */ -LTC4245_ALARM(in5_min_alarm, (1 << 0), LTC4245_FAULT2); -LTC4245_ALARM(in6_min_alarm, (1 << 1), LTC4245_FAULT2); -LTC4245_ALARM(in7_min_alarm, (1 << 2), LTC4245_FAULT2); -LTC4245_ALARM(in8_min_alarm, (1 << 3), LTC4245_FAULT2); - -/* GPIO voltages */ -LTC4245_GPIO_VOLTAGE(in9_input, 0); -LTC4245_GPIO_VOLTAGE(in10_input, 1); -LTC4245_GPIO_VOLTAGE(in11_input, 2); - -/* Power Consumption (virtual) */ -LTC4245_POWER(power1_input, LTC4245_12VSENSE); -LTC4245_POWER(power2_input, LTC4245_5VSENSE); -LTC4245_POWER(power3_input, LTC4245_3VSENSE); -LTC4245_POWER(power4_input, LTC4245_VEESENSE); - -/* - * Finally, construct an array of pointers to members of the above objects, - * as required for sysfs_create_group() - */ -static struct attribute *ltc4245_std_attributes[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - - &sensor_dev_attr_in1_min_alarm.dev_attr.attr, - &sensor_dev_attr_in2_min_alarm.dev_attr.attr, - &sensor_dev_attr_in3_min_alarm.dev_attr.attr, - &sensor_dev_attr_in4_min_alarm.dev_attr.attr, - - &sensor_dev_attr_curr1_input.dev_attr.attr, - &sensor_dev_attr_curr2_input.dev_attr.attr, - &sensor_dev_attr_curr3_input.dev_attr.attr, - &sensor_dev_attr_curr4_input.dev_attr.attr, - - &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, - &sensor_dev_attr_curr2_max_alarm.dev_attr.attr, - &sensor_dev_attr_curr3_max_alarm.dev_attr.attr, - &sensor_dev_attr_curr4_max_alarm.dev_attr.attr, - - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - - &sensor_dev_attr_in5_min_alarm.dev_attr.attr, - &sensor_dev_attr_in6_min_alarm.dev_attr.attr, - &sensor_dev_attr_in7_min_alarm.dev_attr.attr, - &sensor_dev_attr_in8_min_alarm.dev_attr.attr, - - &sensor_dev_attr_in9_input.dev_attr.attr, - - &sensor_dev_attr_power1_input.dev_attr.attr, - &sensor_dev_attr_power2_input.dev_attr.attr, - &sensor_dev_attr_power3_input.dev_attr.attr, - &sensor_dev_attr_power4_input.dev_attr.attr, - - NULL, -}; - -static struct attribute *ltc4245_gpio_attributes[] = { - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ltc4245_std_group = { - .attrs = ltc4245_std_attributes, -}; - -static const struct attribute_group ltc4245_gpio_group = { - .attrs = ltc4245_gpio_attributes, -}; - -static int ltc4245_sysfs_create_groups(struct i2c_client *client) -{ - struct ltc4245_data *data = i2c_get_clientdata(client); - struct device *dev = &client->dev; - int ret; - - /* register the standard sysfs attributes */ - ret = sysfs_create_group(&dev->kobj, <c4245_std_group); - if (ret) { - dev_err(dev, "unable to register standard attributes\n"); - return ret; - } - - /* if we're using the extra gpio support, register it's attributes */ - if (data->use_extra_gpios) { - ret = sysfs_create_group(&dev->kobj, <c4245_gpio_group); - if (ret) { - dev_err(dev, "unable to register gpio attributes\n"); - sysfs_remove_group(&dev->kobj, <c4245_std_group); - return ret; - } - } - - return 0; -} - -static void ltc4245_sysfs_remove_groups(struct i2c_client *client) -{ - struct ltc4245_data *data = i2c_get_clientdata(client); - struct device *dev = &client->dev; - - if (data->use_extra_gpios) - sysfs_remove_group(&dev->kobj, <c4245_gpio_group); - - sysfs_remove_group(&dev->kobj, <c4245_std_group); -} - -static bool ltc4245_use_extra_gpios(struct i2c_client *client) -{ - struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev); -#ifdef CONFIG_OF - struct device_node *np = client->dev.of_node; -#endif - - /* prefer platform data */ - if (pdata) - return pdata->use_extra_gpios; - -#ifdef CONFIG_OF - /* fallback on OF */ - if (of_find_property(np, "ltc4245,use-extra-gpios", NULL)) - return true; -#endif - - return false; -} - -static int ltc4245_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct ltc4245_data *data; - int ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto out_kzalloc; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->use_extra_gpios = ltc4245_use_extra_gpios(client); - - /* Initialize the LTC4245 chip */ - i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00); - i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00); - - /* Register sysfs hooks */ - ret = ltc4245_sysfs_create_groups(client); - if (ret) - goto out_sysfs_create_groups; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_hwmon_device_register; - } - - return 0; - -out_hwmon_device_register: - ltc4245_sysfs_remove_groups(client); -out_sysfs_create_groups: - kfree(data); -out_kzalloc: - return ret; -} - -static int ltc4245_remove(struct i2c_client *client) -{ - struct ltc4245_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - ltc4245_sysfs_remove_groups(client); - kfree(data); - - return 0; -} - -static const struct i2c_device_id ltc4245_id[] = { - { "ltc4245", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ltc4245_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ltc4245_driver = { - .driver = { - .name = "ltc4245", - }, - .probe = ltc4245_probe, - .remove = ltc4245_remove, - .id_table = ltc4245_id, -}; - -module_i2c_driver(ltc4245_driver); - -MODULE_AUTHOR("Ira W. Snyder "); -MODULE_DESCRIPTION("LTC4245 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ltc4261.c b/ANDROID_3.4.5/drivers/hwmon/ltc4261.c deleted file mode 100644 index 069b7d34..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ltc4261.c +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Driver for Linear Technology LTC4261 I2C Negative Voltage Hot Swap Controller - * - * Copyright (C) 2010 Ericsson AB. - * - * Derived from: - * - * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller - * Copyright (C) 2008 Ira W. Snyder - * - * Datasheet: http://cds.linear.com/docs/Datasheet/42612fb.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* chip registers */ -#define LTC4261_STATUS 0x00 /* readonly */ -#define LTC4261_FAULT 0x01 -#define LTC4261_ALERT 0x02 -#define LTC4261_CONTROL 0x03 -#define LTC4261_SENSE_H 0x04 -#define LTC4261_SENSE_L 0x05 -#define LTC4261_ADIN2_H 0x06 -#define LTC4261_ADIN2_L 0x07 -#define LTC4261_ADIN_H 0x08 -#define LTC4261_ADIN_L 0x09 - -/* - * Fault register bits - */ -#define FAULT_OV (1<<0) -#define FAULT_UV (1<<1) -#define FAULT_OC (1<<2) - -struct ltc4261_data { - struct device *hwmon_dev; - - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - - /* Registers */ - u8 regs[10]; -}; - -static struct ltc4261_data *ltc4261_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct ltc4261_data *data = i2c_get_clientdata(client); - struct ltc4261_data *ret = data; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ / 4) || !data->valid) { - int i; - - /* Read registers -- 0x00 to 0x09 */ - for (i = 0; i < ARRAY_SIZE(data->regs); i++) { - int val; - - val = i2c_smbus_read_byte_data(client, i); - if (unlikely(val < 0)) { - dev_dbg(dev, - "Failed to read ADC value: error %d\n", - val); - ret = ERR_PTR(val); - data->valid = 0; - goto abort; - } - data->regs[i] = val; - } - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -/* Return the voltage from the given register in mV or mA */ -static int ltc4261_get_value(struct ltc4261_data *data, u8 reg) -{ - u32 val; - - val = (data->regs[reg] << 2) + (data->regs[reg + 1] >> 6); - - switch (reg) { - case LTC4261_ADIN_H: - case LTC4261_ADIN2_H: - /* 2.5mV resolution. Convert to mV. */ - val = val * 25 / 10; - break; - case LTC4261_SENSE_H: - /* - * 62.5uV resolution. Convert to current as measured with - * an 1 mOhm sense resistor, in mA. If a different sense - * resistor is installed, calculate the actual current by - * dividing the reported current by the sense resistor value - * in mOhm. - */ - val = val * 625 / 10; - break; - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - val = 0; - break; - } - - return val; -} - -static ssize_t ltc4261_show_value(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct ltc4261_data *data = ltc4261_update_device(dev); - int value; - - if (IS_ERR(data)) - return PTR_ERR(data); - - value = ltc4261_get_value(data, attr->index); - return snprintf(buf, PAGE_SIZE, "%d\n", value); -} - -static ssize_t ltc4261_show_bool(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct ltc4261_data *data = ltc4261_update_device(dev); - u8 fault; - - if (IS_ERR(data)) - return PTR_ERR(data); - - fault = data->regs[LTC4261_FAULT] & attr->index; - if (fault) /* Clear reported faults in chip register */ - i2c_smbus_write_byte_data(client, LTC4261_FAULT, ~fault); - - return snprintf(buf, PAGE_SIZE, "%d\n", fault ? 1 : 0); -} - -/* - * These macros are used below in constructing device attribute objects - * for use with sysfs_create_group() to make a sysfs device file - * for each register. - */ - -#define LTC4261_VALUE(name, ltc4261_cmd_idx) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4261_show_value, NULL, ltc4261_cmd_idx) - -#define LTC4261_BOOL(name, mask) \ - static SENSOR_DEVICE_ATTR(name, S_IRUGO, \ - ltc4261_show_bool, NULL, (mask)) - -/* - * Input voltages. - */ -LTC4261_VALUE(in1_input, LTC4261_ADIN_H); -LTC4261_VALUE(in2_input, LTC4261_ADIN2_H); - -/* - * Voltage alarms. The chip has only one set of voltage alarm status bits, - * triggered by input voltage alarms. In many designs, those alarms are - * associated with the ADIN2 sensor, due to the proximity of the ADIN2 pin - * to the OV pin. ADIN2 is, however, not available on all chip variants. - * To ensure that the alarm condition is reported to the user, report it - * with both voltage sensors. - */ -LTC4261_BOOL(in1_min_alarm, FAULT_UV); -LTC4261_BOOL(in1_max_alarm, FAULT_OV); -LTC4261_BOOL(in2_min_alarm, FAULT_UV); -LTC4261_BOOL(in2_max_alarm, FAULT_OV); - -/* Currents (via sense resistor) */ -LTC4261_VALUE(curr1_input, LTC4261_SENSE_H); - -/* Overcurrent alarm */ -LTC4261_BOOL(curr1_max_alarm, FAULT_OC); - -static struct attribute *ltc4261_attributes[] = { - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_min_alarm.dev_attr.attr, - &sensor_dev_attr_in1_max_alarm.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_min_alarm.dev_attr.attr, - &sensor_dev_attr_in2_max_alarm.dev_attr.attr, - - &sensor_dev_attr_curr1_input.dev_attr.attr, - &sensor_dev_attr_curr1_max_alarm.dev_attr.attr, - - NULL, -}; - -static const struct attribute_group ltc4261_group = { - .attrs = ltc4261_attributes, -}; - -static int ltc4261_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct ltc4261_data *data; - int ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - if (i2c_smbus_read_byte_data(client, LTC4261_STATUS) < 0) { - dev_err(&client->dev, "Failed to read status register\n"); - return -ENODEV; - } - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Clear faults */ - i2c_smbus_write_byte_data(client, LTC4261_FAULT, 0x00); - - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, <c4261_group); - if (ret) - return ret; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_hwmon_device_register; - } - - return 0; - -out_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, <c4261_group); - return ret; -} - -static int ltc4261_remove(struct i2c_client *client) -{ - struct ltc4261_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, <c4261_group); - - return 0; -} - -static const struct i2c_device_id ltc4261_id[] = { - {"ltc4261", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, ltc4261_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver ltc4261_driver = { - .driver = { - .name = "ltc4261", - }, - .probe = ltc4261_probe, - .remove = ltc4261_remove, - .id_table = ltc4261_id, -}; - -module_i2c_driver(ltc4261_driver); - -MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("LTC4261 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max1111.c b/ANDROID_3.4.5/drivers/hwmon/max1111.c deleted file mode 100644 index 362a40eb..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max1111.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * max1111.c - +2.7V, Low-Power, Multichannel, Serial 8-bit ADCs - * - * Based on arch/arm/mach-pxa/corgi_ssp.c - * - * Copyright (C) 2004-2005 Richard Purdie - * - * Copyright (C) 2008 Marvell International Ltd. - * Eric Miao - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * publishhed by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define MAX1111_TX_BUF_SIZE 1 -#define MAX1111_RX_BUF_SIZE 2 - -/* MAX1111 Commands */ -#define MAX1111_CTRL_PD0 (1u << 0) -#define MAX1111_CTRL_PD1 (1u << 1) -#define MAX1111_CTRL_SGL (1u << 2) -#define MAX1111_CTRL_UNI (1u << 3) -#define MAX1111_CTRL_SEL_SH (5) /* NOTE: bit 4 is ignored */ -#define MAX1111_CTRL_STR (1u << 7) - -struct max1111_data { - struct spi_device *spi; - struct device *hwmon_dev; - struct spi_message msg; - struct spi_transfer xfer[2]; - uint8_t tx_buf[MAX1111_TX_BUF_SIZE]; - uint8_t rx_buf[MAX1111_RX_BUF_SIZE]; - struct mutex drvdata_lock; - /* protect msg, xfer and buffers from multiple access */ -}; - -static int max1111_read(struct device *dev, int channel) -{ - struct max1111_data *data = dev_get_drvdata(dev); - uint8_t v1, v2; - int err; - - /* writing to drvdata struct is not thread safe, wait on mutex */ - mutex_lock(&data->drvdata_lock); - - data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) | - MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | - MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR; - - err = spi_sync(data->spi, &data->msg); - if (err < 0) { - dev_err(dev, "spi_sync failed with %d\n", err); - mutex_unlock(&data->drvdata_lock); - return err; - } - - v1 = data->rx_buf[0]; - v2 = data->rx_buf[1]; - - mutex_unlock(&data->drvdata_lock); - - if ((v1 & 0xc0) || (v2 & 0x3f)) - return -EINVAL; - - return (v1 << 2) | (v2 >> 6); -} - -#ifdef CONFIG_SHARPSL_PM -static struct max1111_data *the_max1111; - -int max1111_read_channel(int channel) -{ - return max1111_read(&the_max1111->spi->dev, channel); -} -EXPORT_SYMBOL(max1111_read_channel); -#endif - -/* - * NOTE: SPI devices do not have a default 'name' attribute, which is - * likely to be used by hwmon applications to distinguish between - * different devices, explicitly add a name attribute here. - */ -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "max1111\n"); -} - -static ssize_t show_adc(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int channel = to_sensor_dev_attr(attr)->index; - int ret; - - ret = max1111_read(dev, channel); - if (ret < 0) - return ret; - - /* - * assume the reference voltage to be 2.048V, with an 8-bit sample, - * the LSB weight is 8mV - */ - return sprintf(buf, "%d\n", ret * 8); -} - -#define MAX1111_ADC_ATTR(_id) \ - SENSOR_DEVICE_ATTR(in##_id##_input, S_IRUGO, show_adc, NULL, _id) - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static MAX1111_ADC_ATTR(0); -static MAX1111_ADC_ATTR(1); -static MAX1111_ADC_ATTR(2); -static MAX1111_ADC_ATTR(3); - -static struct attribute *max1111_attributes[] = { - &dev_attr_name.attr, - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - NULL, -}; - -static const struct attribute_group max1111_attr_group = { - .attrs = max1111_attributes, -}; - -static int __devinit setup_transfer(struct max1111_data *data) -{ - struct spi_message *m; - struct spi_transfer *x; - - m = &data->msg; - x = &data->xfer[0]; - - spi_message_init(m); - - x->tx_buf = &data->tx_buf[0]; - x->len = MAX1111_TX_BUF_SIZE; - spi_message_add_tail(x, m); - - x++; - x->rx_buf = &data->rx_buf[0]; - x->len = MAX1111_RX_BUF_SIZE; - spi_message_add_tail(x, m); - - return 0; -} - -static int __devinit max1111_probe(struct spi_device *spi) -{ - struct max1111_data *data; - int err; - - spi->bits_per_word = 8; - spi->mode = SPI_MODE_0; - err = spi_setup(spi); - if (err < 0) - return err; - - data = kzalloc(sizeof(struct max1111_data), GFP_KERNEL); - if (data == NULL) { - dev_err(&spi->dev, "failed to allocate memory\n"); - return -ENOMEM; - } - - err = setup_transfer(data); - if (err) - goto err_free_data; - - mutex_init(&data->drvdata_lock); - - data->spi = spi; - spi_set_drvdata(spi, data); - - err = sysfs_create_group(&spi->dev.kobj, &max1111_attr_group); - if (err) { - dev_err(&spi->dev, "failed to create attribute group\n"); - goto err_free_data; - } - - data->hwmon_dev = hwmon_device_register(&spi->dev); - if (IS_ERR(data->hwmon_dev)) { - dev_err(&spi->dev, "failed to create hwmon device\n"); - err = PTR_ERR(data->hwmon_dev); - goto err_remove; - } - -#ifdef CONFIG_SHARPSL_PM - the_max1111 = data; -#endif - return 0; - -err_remove: - sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); -err_free_data: - kfree(data); - return err; -} - -static int __devexit max1111_remove(struct spi_device *spi) -{ - struct max1111_data *data = spi_get_drvdata(spi); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); - mutex_destroy(&data->drvdata_lock); - kfree(data); - return 0; -} - -static struct spi_driver max1111_driver = { - .driver = { - .name = "max1111", - .owner = THIS_MODULE, - }, - .probe = max1111_probe, - .remove = __devexit_p(max1111_remove), -}; - -module_spi_driver(max1111_driver); - -MODULE_AUTHOR("Eric Miao "); -MODULE_DESCRIPTION("MAX1111 ADC Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:max1111"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max16065.c b/ANDROID_3.4.5/drivers/hwmon/max16065.c deleted file mode 100644 index 822261be..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max16065.c +++ /dev/null @@ -1,697 +0,0 @@ -/* - * Driver for - * Maxim MAX16065/MAX16066 12-Channel/8-Channel, Flash-Configurable - * System Managers with Nonvolatile Fault Registers - * Maxim MAX16067/MAX16068 6-Channel, Flash-Configurable System Managers - * with Nonvolatile Fault Registers - * Maxim MAX16070/MAX16071 12-Channel/8-Channel, Flash-Configurable System - * Monitors with Nonvolatile Fault Registers - * - * Copyright (C) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -enum chips { max16065, max16066, max16067, max16068, max16070, max16071 }; - -/* - * Registers - */ -#define MAX16065_ADC(x) ((x) * 2) - -#define MAX16065_CURR_SENSE 0x18 -#define MAX16065_CSP_ADC 0x19 -#define MAX16065_FAULT(x) (0x1b + (x)) -#define MAX16065_SCALE(x) (0x43 + (x)) -#define MAX16065_CURR_CONTROL 0x47 -#define MAX16065_LIMIT(l, x) (0x48 + (l) + (x) * 3) /* - * l: limit - * 0: min/max - * 1: crit - * 2: lcrit - * x: ADC index - */ - -#define MAX16065_SW_ENABLE 0x73 - -#define MAX16065_WARNING_OV (1 << 3) /* Set if secondary threshold is OV - warning */ - -#define MAX16065_CURR_ENABLE (1 << 0) - -#define MAX16065_NUM_LIMIT 3 -#define MAX16065_NUM_ADC 12 /* maximum number of ADC channels */ - -static const int max16065_num_adc[] = { - [max16065] = 12, - [max16066] = 8, - [max16067] = 6, - [max16068] = 6, - [max16070] = 12, - [max16071] = 8, -}; - -static const bool max16065_have_secondary[] = { - [max16065] = true, - [max16066] = true, - [max16067] = false, - [max16068] = false, - [max16070] = true, - [max16071] = true, -}; - -static const bool max16065_have_current[] = { - [max16065] = true, - [max16066] = true, - [max16067] = false, - [max16068] = false, - [max16070] = true, - [max16071] = true, -}; - -struct max16065_data { - enum chips type; - struct device *hwmon_dev; - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - int num_adc; - bool have_current; - int curr_gain; - /* limits are in mV */ - int limit[MAX16065_NUM_LIMIT][MAX16065_NUM_ADC]; - int range[MAX16065_NUM_ADC + 1];/* voltage range */ - int adc[MAX16065_NUM_ADC + 1]; /* adc values (raw) including csp_adc */ - int curr_sense; - int fault[2]; -}; - -static const int max16065_adc_range[] = { 5560, 2780, 1390, 0 }; -static const int max16065_csp_adc_range[] = { 7000, 14000 }; - -/* ADC registers have 10 bit resolution. */ -static inline int ADC_TO_MV(int adc, int range) -{ - return (adc * range) / 1024; -} - -/* - * Limit registers have 8 bit resolution and match upper 8 bits of ADC - * registers. - */ -static inline int LIMIT_TO_MV(int limit, int range) -{ - return limit * range / 256; -} - -static inline int MV_TO_LIMIT(int mv, int range) -{ - return SENSORS_LIMIT(DIV_ROUND_CLOSEST(mv * 256, range), 0, 255); -} - -static inline int ADC_TO_CURR(int adc, int gain) -{ - return adc * 1400000 / (gain * 255); -} - -/* - * max16065_read_adc() - * - * Read 16 bit value from , . - * Upper 8 bits are in , lower 2 bits are in bits 7:6 of . - */ -static int max16065_read_adc(struct i2c_client *client, int reg) -{ - int rv; - - rv = i2c_smbus_read_word_swapped(client, reg); - if (unlikely(rv < 0)) - return rv; - return rv >> 6; -} - -static struct max16065_data *max16065_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max16065_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int i; - - for (i = 0; i < data->num_adc; i++) - data->adc[i] - = max16065_read_adc(client, MAX16065_ADC(i)); - - if (data->have_current) { - data->adc[MAX16065_NUM_ADC] - = max16065_read_adc(client, MAX16065_CSP_ADC); - data->curr_sense - = i2c_smbus_read_byte_data(client, - MAX16065_CURR_SENSE); - } - - for (i = 0; i < DIV_ROUND_UP(data->num_adc, 8); i++) - data->fault[i] - = i2c_smbus_read_byte_data(client, MAX16065_FAULT(i)); - - data->last_updated = jiffies; - data->valid = 1; - } - mutex_unlock(&data->update_lock); - return data; -} - -static ssize_t max16065_show_alarm(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da); - struct max16065_data *data = max16065_update_device(dev); - int val = data->fault[attr2->nr]; - - if (val < 0) - return val; - - val &= (1 << attr2->index); - if (val) - i2c_smbus_write_byte_data(to_i2c_client(dev), - MAX16065_FAULT(attr2->nr), val); - - return snprintf(buf, PAGE_SIZE, "%d\n", !!val); -} - -static ssize_t max16065_show_input(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct max16065_data *data = max16065_update_device(dev); - int adc = data->adc[attr->index]; - - if (unlikely(adc < 0)) - return adc; - - return snprintf(buf, PAGE_SIZE, "%d\n", - ADC_TO_MV(adc, data->range[attr->index])); -} - -static ssize_t max16065_show_current(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct max16065_data *data = max16065_update_device(dev); - - if (unlikely(data->curr_sense < 0)) - return data->curr_sense; - - return snprintf(buf, PAGE_SIZE, "%d\n", - ADC_TO_CURR(data->curr_sense, data->curr_gain)); -} - -static ssize_t max16065_set_limit(struct device *dev, - struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da); - struct i2c_client *client = to_i2c_client(dev); - struct max16065_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - int limit; - - err = kstrtoul(buf, 10, &val); - if (unlikely(err < 0)) - return err; - - limit = MV_TO_LIMIT(val, data->range[attr2->index]); - - mutex_lock(&data->update_lock); - data->limit[attr2->nr][attr2->index] - = LIMIT_TO_MV(limit, data->range[attr2->index]); - i2c_smbus_write_byte_data(client, - MAX16065_LIMIT(attr2->nr, attr2->index), - limit); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t max16065_show_limit(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(da); - struct i2c_client *client = to_i2c_client(dev); - struct max16065_data *data = i2c_get_clientdata(client); - - return snprintf(buf, PAGE_SIZE, "%d\n", - data->limit[attr2->nr][attr2->index]); -} - -/* Construct a sensor_device_attribute structure for each register */ - -/* Input voltages */ -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, max16065_show_input, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, max16065_show_input, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, max16065_show_input, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, max16065_show_input, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, max16065_show_input, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, max16065_show_input, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, max16065_show_input, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, max16065_show_input, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, max16065_show_input, NULL, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, max16065_show_input, NULL, 9); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, max16065_show_input, NULL, 10); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, max16065_show_input, NULL, 11); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, max16065_show_input, NULL, 12); - -/* Input voltages lcrit */ -static SENSOR_DEVICE_ATTR_2(in0_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 0); -static SENSOR_DEVICE_ATTR_2(in1_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 1); -static SENSOR_DEVICE_ATTR_2(in2_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 2); -static SENSOR_DEVICE_ATTR_2(in3_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 3); -static SENSOR_DEVICE_ATTR_2(in4_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 4); -static SENSOR_DEVICE_ATTR_2(in5_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 5); -static SENSOR_DEVICE_ATTR_2(in6_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 6); -static SENSOR_DEVICE_ATTR_2(in7_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 7); -static SENSOR_DEVICE_ATTR_2(in8_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 8); -static SENSOR_DEVICE_ATTR_2(in9_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 9); -static SENSOR_DEVICE_ATTR_2(in10_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 10); -static SENSOR_DEVICE_ATTR_2(in11_lcrit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 2, 11); - -/* Input voltages crit */ -static SENSOR_DEVICE_ATTR_2(in0_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 0); -static SENSOR_DEVICE_ATTR_2(in1_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 1); -static SENSOR_DEVICE_ATTR_2(in2_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 2); -static SENSOR_DEVICE_ATTR_2(in3_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 3); -static SENSOR_DEVICE_ATTR_2(in4_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 4); -static SENSOR_DEVICE_ATTR_2(in5_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 5); -static SENSOR_DEVICE_ATTR_2(in6_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 6); -static SENSOR_DEVICE_ATTR_2(in7_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 7); -static SENSOR_DEVICE_ATTR_2(in8_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 8); -static SENSOR_DEVICE_ATTR_2(in9_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 9); -static SENSOR_DEVICE_ATTR_2(in10_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 10); -static SENSOR_DEVICE_ATTR_2(in11_crit, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 1, 11); - -/* Input voltages min */ -static SENSOR_DEVICE_ATTR_2(in0_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 0); -static SENSOR_DEVICE_ATTR_2(in1_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 1); -static SENSOR_DEVICE_ATTR_2(in2_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 2); -static SENSOR_DEVICE_ATTR_2(in3_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 3); -static SENSOR_DEVICE_ATTR_2(in4_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 4); -static SENSOR_DEVICE_ATTR_2(in5_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 5); -static SENSOR_DEVICE_ATTR_2(in6_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 6); -static SENSOR_DEVICE_ATTR_2(in7_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 7); -static SENSOR_DEVICE_ATTR_2(in8_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 8); -static SENSOR_DEVICE_ATTR_2(in9_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 9); -static SENSOR_DEVICE_ATTR_2(in10_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 10); -static SENSOR_DEVICE_ATTR_2(in11_min, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 11); - -/* Input voltages max */ -static SENSOR_DEVICE_ATTR_2(in0_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 0); -static SENSOR_DEVICE_ATTR_2(in1_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 1); -static SENSOR_DEVICE_ATTR_2(in2_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 2); -static SENSOR_DEVICE_ATTR_2(in3_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 3); -static SENSOR_DEVICE_ATTR_2(in4_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 4); -static SENSOR_DEVICE_ATTR_2(in5_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 5); -static SENSOR_DEVICE_ATTR_2(in6_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 6); -static SENSOR_DEVICE_ATTR_2(in7_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 7); -static SENSOR_DEVICE_ATTR_2(in8_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 8); -static SENSOR_DEVICE_ATTR_2(in9_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 9); -static SENSOR_DEVICE_ATTR_2(in10_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 10); -static SENSOR_DEVICE_ATTR_2(in11_max, S_IWUSR | S_IRUGO, max16065_show_limit, - max16065_set_limit, 0, 11); - -/* alarms */ -static SENSOR_DEVICE_ATTR_2(in0_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 0); -static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 1); -static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 2); -static SENSOR_DEVICE_ATTR_2(in3_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 3); -static SENSOR_DEVICE_ATTR_2(in4_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 4); -static SENSOR_DEVICE_ATTR_2(in5_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 5); -static SENSOR_DEVICE_ATTR_2(in6_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 6); -static SENSOR_DEVICE_ATTR_2(in7_alarm, S_IRUGO, max16065_show_alarm, NULL, - 0, 7); -static SENSOR_DEVICE_ATTR_2(in8_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 0); -static SENSOR_DEVICE_ATTR_2(in9_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 1); -static SENSOR_DEVICE_ATTR_2(in10_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 2); -static SENSOR_DEVICE_ATTR_2(in11_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 3); - -/* Current and alarm */ -static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, max16065_show_current, NULL, 0); -static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, max16065_show_alarm, NULL, - 1, 4); - -/* - * Finally, construct an array of pointers to members of the above objects, - * as required for sysfs_create_group() - */ -static struct attribute *max16065_basic_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_lcrit.dev_attr.attr, - &sensor_dev_attr_in0_crit.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_lcrit.dev_attr.attr, - &sensor_dev_attr_in1_crit.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_lcrit.dev_attr.attr, - &sensor_dev_attr_in2_crit.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_lcrit.dev_attr.attr, - &sensor_dev_attr_in3_crit.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_lcrit.dev_attr.attr, - &sensor_dev_attr_in4_crit.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_lcrit.dev_attr.attr, - &sensor_dev_attr_in5_crit.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_lcrit.dev_attr.attr, - &sensor_dev_attr_in6_crit.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in7_lcrit.dev_attr.attr, - &sensor_dev_attr_in7_crit.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_lcrit.dev_attr.attr, - &sensor_dev_attr_in8_crit.dev_attr.attr, - &sensor_dev_attr_in8_alarm.dev_attr.attr, - - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in9_lcrit.dev_attr.attr, - &sensor_dev_attr_in9_crit.dev_attr.attr, - &sensor_dev_attr_in9_alarm.dev_attr.attr, - - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in10_lcrit.dev_attr.attr, - &sensor_dev_attr_in10_crit.dev_attr.attr, - &sensor_dev_attr_in10_alarm.dev_attr.attr, - - &sensor_dev_attr_in11_input.dev_attr.attr, - &sensor_dev_attr_in11_lcrit.dev_attr.attr, - &sensor_dev_attr_in11_crit.dev_attr.attr, - &sensor_dev_attr_in11_alarm.dev_attr.attr, - - NULL -}; - -static struct attribute *max16065_current_attributes[] = { - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_curr1_input.dev_attr.attr, - &sensor_dev_attr_curr1_alarm.dev_attr.attr, - NULL -}; - -static struct attribute *max16065_min_attributes[] = { - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in9_min.dev_attr.attr, - &sensor_dev_attr_in10_min.dev_attr.attr, - &sensor_dev_attr_in11_min.dev_attr.attr, - NULL -}; - -static struct attribute *max16065_max_attributes[] = { - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in9_max.dev_attr.attr, - &sensor_dev_attr_in10_max.dev_attr.attr, - &sensor_dev_attr_in11_max.dev_attr.attr, - NULL -}; - -static const struct attribute_group max16065_basic_group = { - .attrs = max16065_basic_attributes, -}; - -static const struct attribute_group max16065_current_group = { - .attrs = max16065_current_attributes, -}; - -static const struct attribute_group max16065_min_group = { - .attrs = max16065_min_attributes, -}; - -static const struct attribute_group max16065_max_group = { - .attrs = max16065_max_attributes, -}; - -static void max16065_cleanup(struct i2c_client *client) -{ - sysfs_remove_group(&client->dev.kobj, &max16065_max_group); - sysfs_remove_group(&client->dev.kobj, &max16065_min_group); - sysfs_remove_group(&client->dev.kobj, &max16065_current_group); - sysfs_remove_group(&client->dev.kobj, &max16065_basic_group); -} - -static int max16065_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct max16065_data *data; - int i, j, val, ret; - bool have_secondary; /* true if chip has secondary limits */ - bool secondary_is_max = false; /* secondary limits reflect max */ - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (unlikely(!data)) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - data->num_adc = max16065_num_adc[id->driver_data]; - data->have_current = max16065_have_current[id->driver_data]; - have_secondary = max16065_have_secondary[id->driver_data]; - - if (have_secondary) { - val = i2c_smbus_read_byte_data(client, MAX16065_SW_ENABLE); - if (unlikely(val < 0)) - return val; - secondary_is_max = val & MAX16065_WARNING_OV; - } - - /* Read scale registers, convert to range */ - for (i = 0; i < DIV_ROUND_UP(data->num_adc, 4); i++) { - val = i2c_smbus_read_byte_data(client, MAX16065_SCALE(i)); - if (unlikely(val < 0)) - return val; - for (j = 0; j < 4 && i * 4 + j < data->num_adc; j++) { - data->range[i * 4 + j] = - max16065_adc_range[(val >> (j * 2)) & 0x3]; - } - } - - /* Read limits */ - for (i = 0; i < MAX16065_NUM_LIMIT; i++) { - if (i == 0 && !have_secondary) - continue; - - for (j = 0; j < data->num_adc; j++) { - val = i2c_smbus_read_byte_data(client, - MAX16065_LIMIT(i, j)); - if (unlikely(val < 0)) - return val; - data->limit[i][j] = LIMIT_TO_MV(val, data->range[j]); - } - } - - /* Register sysfs hooks */ - for (i = 0; i < data->num_adc * 4; i++) { - /* Do not create sysfs entry if channel is disabled */ - if (!data->range[i / 4]) - continue; - - ret = sysfs_create_file(&client->dev.kobj, - max16065_basic_attributes[i]); - if (unlikely(ret)) - goto out; - } - - if (have_secondary) { - struct attribute **attr = secondary_is_max ? - max16065_max_attributes : max16065_min_attributes; - - for (i = 0; i < data->num_adc; i++) { - if (!data->range[i]) - continue; - - ret = sysfs_create_file(&client->dev.kobj, attr[i]); - if (unlikely(ret)) - goto out; - } - } - - if (data->have_current) { - val = i2c_smbus_read_byte_data(client, MAX16065_CURR_CONTROL); - if (unlikely(val < 0)) { - ret = val; - goto out; - } - if (val & MAX16065_CURR_ENABLE) { - /* - * Current gain is 6, 12, 24, 48 based on values in - * bit 2,3. - */ - data->curr_gain = 6 << ((val >> 2) & 0x03); - data->range[MAX16065_NUM_ADC] - = max16065_csp_adc_range[(val >> 1) & 0x01]; - ret = sysfs_create_group(&client->dev.kobj, - &max16065_current_group); - if (unlikely(ret)) - goto out; - } else { - data->have_current = false; - } - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (unlikely(IS_ERR(data->hwmon_dev))) { - ret = PTR_ERR(data->hwmon_dev); - goto out; - } - return 0; - -out: - max16065_cleanup(client); - return ret; -} - -static int max16065_remove(struct i2c_client *client) -{ - struct max16065_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - max16065_cleanup(client); - - return 0; -} - -static const struct i2c_device_id max16065_id[] = { - { "max16065", max16065 }, - { "max16066", max16066 }, - { "max16067", max16067 }, - { "max16068", max16068 }, - { "max16070", max16070 }, - { "max16071", max16071 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, max16065_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver max16065_driver = { - .driver = { - .name = "max16065", - }, - .probe = max16065_probe, - .remove = max16065_remove, - .id_table = max16065_id, -}; - -module_i2c_driver(max16065_driver); - -MODULE_AUTHOR("Guenter Roeck "); -MODULE_DESCRIPTION("MAX16065 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max1619.c b/ANDROID_3.4.5/drivers/hwmon/max1619.c deleted file mode 100644 index ecac04a7..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max1619.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * max1619.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2003-2004 Alexey Fisher - * Jean Delvare - * - * Based on the lm90 driver. The MAX1619 is a sensor chip made by Maxim. - * It reports up to two temperatures (its own plus up to - * one external one). Complete datasheet can be - * obtained from Maxim's website at: - * http://pdfserv.maxim-ic.com/en/ds/MAX1619.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const unsigned short normal_i2c[] = { - 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; - -/* - * The MAX1619 registers - */ - -#define MAX1619_REG_R_MAN_ID 0xFE -#define MAX1619_REG_R_CHIP_ID 0xFF -#define MAX1619_REG_R_CONFIG 0x03 -#define MAX1619_REG_W_CONFIG 0x09 -#define MAX1619_REG_R_CONVRATE 0x04 -#define MAX1619_REG_W_CONVRATE 0x0A -#define MAX1619_REG_R_STATUS 0x02 -#define MAX1619_REG_R_LOCAL_TEMP 0x00 -#define MAX1619_REG_R_REMOTE_TEMP 0x01 -#define MAX1619_REG_R_REMOTE_HIGH 0x07 -#define MAX1619_REG_W_REMOTE_HIGH 0x0D -#define MAX1619_REG_R_REMOTE_LOW 0x08 -#define MAX1619_REG_W_REMOTE_LOW 0x0E -#define MAX1619_REG_R_REMOTE_CRIT 0x10 -#define MAX1619_REG_W_REMOTE_CRIT 0x12 -#define MAX1619_REG_R_TCRIT_HYST 0x11 -#define MAX1619_REG_W_TCRIT_HYST 0x13 - -/* - * Conversions - */ - -static int temp_from_reg(int val) -{ - return (val & 0x80 ? val-0x100 : val) * 1000; -} - -static int temp_to_reg(int val) -{ - return (val < 0 ? val+0x100*1000 : val) / 1000; -} - -/* - * Functions declaration - */ - -static int max1619_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int max1619_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void max1619_init_client(struct i2c_client *client); -static int max1619_remove(struct i2c_client *client); -static struct max1619_data *max1619_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id max1619_id[] = { - { "max1619", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max1619_id); - -static struct i2c_driver max1619_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "max1619", - }, - .probe = max1619_probe, - .remove = max1619_remove, - .id_table = max1619_id, - .detect = max1619_detect, - .address_list = normal_i2c, -}; - -/* - * Client data (each client gets its own) - */ - -struct max1619_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - u8 temp_input1; /* local */ - u8 temp_input2, temp_low2, temp_high2; /* remote */ - u8 temp_crit2; - u8 temp_hyst2; - u8 alarms; -}; - -/* - * Sysfs stuff - */ - -#define show_temp(value) \ -static ssize_t show_##value(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct max1619_data *data = max1619_update_device(dev); \ - return sprintf(buf, "%d\n", temp_from_reg(data->value)); \ -} -show_temp(temp_input1); -show_temp(temp_input2); -show_temp(temp_low2); -show_temp(temp_high2); -show_temp(temp_crit2); -show_temp(temp_hyst2); - -#define set_temp2(value, reg) \ -static ssize_t set_##value(struct device *dev, struct device_attribute *attr, \ - const char *buf, \ - size_t count) \ -{ \ - struct i2c_client *client = to_i2c_client(dev); \ - struct max1619_data *data = i2c_get_clientdata(client); \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ -\ - mutex_lock(&data->update_lock); \ - data->value = temp_to_reg(val); \ - i2c_smbus_write_byte_data(client, reg, data->value); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -set_temp2(temp_low2, MAX1619_REG_W_REMOTE_LOW); -set_temp2(temp_high2, MAX1619_REG_W_REMOTE_HIGH); -set_temp2(temp_crit2, MAX1619_REG_W_REMOTE_CRIT); -set_temp2(temp_hyst2, MAX1619_REG_W_TCRIT_HYST); - -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct max1619_data *data = max1619_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct max1619_data *data = max1619_update_device(dev); - return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL); -static DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input2, NULL); -static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_low2, - set_temp_low2); -static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_high2, - set_temp_high2); -static DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit2, - set_temp_crit2); -static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp_hyst2, - set_temp_hyst2); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); - -static struct attribute *max1619_attributes[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp2_input.attr, - &dev_attr_temp2_min.attr, - &dev_attr_temp2_max.attr, - &dev_attr_temp2_crit.attr, - &dev_attr_temp2_crit_hyst.attr, - - &dev_attr_alarms.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group max1619_group = { - .attrs = max1619_attributes, -}; - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max1619_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u8 reg_config, reg_convrate, reg_status, man_id, chip_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* detection */ - reg_config = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONFIG); - reg_convrate = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONVRATE); - reg_status = i2c_smbus_read_byte_data(client, MAX1619_REG_R_STATUS); - if ((reg_config & 0x03) != 0x00 - || reg_convrate > 0x07 || (reg_status & 0x61) != 0x00) { - dev_dbg(&adapter->dev, "MAX1619 detection failed at 0x%02x\n", - client->addr); - return -ENODEV; - } - - /* identification */ - man_id = i2c_smbus_read_byte_data(client, MAX1619_REG_R_MAN_ID); - chip_id = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CHIP_ID); - if (man_id != 0x4D || chip_id != 0x04) { - dev_info(&adapter->dev, - "Unsupported chip (man_id=0x%02X, chip_id=0x%02X).\n", - man_id, chip_id); - return -ENODEV; - } - - strlcpy(info->type, "max1619", I2C_NAME_SIZE); - - return 0; -} - -static int max1619_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct max1619_data *data; - int err; - - data = kzalloc(sizeof(struct max1619_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Initialize the MAX1619 chip */ - max1619_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &max1619_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &max1619_group); -exit_free: - kfree(data); -exit: - return err; -} - -static void max1619_init_client(struct i2c_client *client) -{ - u8 config; - - /* - * Start the conversions. - */ - i2c_smbus_write_byte_data(client, MAX1619_REG_W_CONVRATE, - 5); /* 2 Hz */ - config = i2c_smbus_read_byte_data(client, MAX1619_REG_R_CONFIG); - if (config & 0x40) - i2c_smbus_write_byte_data(client, MAX1619_REG_W_CONFIG, - config & 0xBF); /* run */ -} - -static int max1619_remove(struct i2c_client *client) -{ - struct max1619_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &max1619_group); - - kfree(data); - return 0; -} - -static struct max1619_data *max1619_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max1619_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - dev_dbg(&client->dev, "Updating max1619 data.\n"); - data->temp_input1 = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_LOCAL_TEMP); - data->temp_input2 = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_REMOTE_TEMP); - data->temp_high2 = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_REMOTE_HIGH); - data->temp_low2 = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_REMOTE_LOW); - data->temp_crit2 = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_REMOTE_CRIT); - data->temp_hyst2 = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_TCRIT_HYST); - data->alarms = i2c_smbus_read_byte_data(client, - MAX1619_REG_R_STATUS); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(max1619_driver); - -MODULE_AUTHOR("Alexey Fisher and " - "Jean Delvare "); -MODULE_DESCRIPTION("MAX1619 sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max1668.c b/ANDROID_3.4.5/drivers/hwmon/max1668.c deleted file mode 100644 index 335b183d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max1668.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (c) 2011 David George - * - * based on adm1021.c - * some credit to Christoph Scheurer, but largely a rewrite - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static unsigned short max1668_addr_list[] = { - 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; - -/* max1668 registers */ - -#define MAX1668_REG_TEMP(nr) (nr) -#define MAX1668_REG_STAT1 0x05 -#define MAX1668_REG_STAT2 0x06 -#define MAX1668_REG_MAN_ID 0xfe -#define MAX1668_REG_DEV_ID 0xff - -/* limits */ - -/* write high limits */ -#define MAX1668_REG_LIMH_WR(nr) (0x13 + 2 * (nr)) -/* write low limits */ -#define MAX1668_REG_LIML_WR(nr) (0x14 + 2 * (nr)) -/* read high limits */ -#define MAX1668_REG_LIMH_RD(nr) (0x08 + 2 * (nr)) -/* read low limits */ -#define MAX1668_REG_LIML_RD(nr) (0x09 + 2 * (nr)) - -/* manufacturer and device ID Constants */ -#define MAN_ID_MAXIM 0x4d -#define DEV_ID_MAX1668 0x3 -#define DEV_ID_MAX1805 0x5 -#define DEV_ID_MAX1989 0xb - -/* read only mode module parameter */ -static bool read_only; -module_param(read_only, bool, 0); -MODULE_PARM_DESC(read_only, "Don't set any values, read only mode"); - -enum chips { max1668, max1805, max1989 }; - -struct max1668_data { - struct device *hwmon_dev; - enum chips type; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* 1x local and 4x remote */ - s8 temp_max[5]; - s8 temp_min[5]; - s8 temp[5]; - u16 alarms; -}; - -static struct max1668_data *max1668_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max1668_data *data = i2c_get_clientdata(client); - struct max1668_data *ret = data; - s32 val; - int i; - - mutex_lock(&data->update_lock); - - if (data->valid && !time_after(jiffies, - data->last_updated + HZ + HZ / 2)) - goto abort; - - for (i = 0; i < 5; i++) { - val = i2c_smbus_read_byte_data(client, MAX1668_REG_TEMP(i)); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->temp[i] = (s8) val; - - val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIMH_RD(i)); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_max[i] = (s8) val; - - val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIML_RD(i)); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_min[i] = (s8) val; - } - - val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT1); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->alarms = val << 8; - - val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT2); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->alarms |= val; - - data->last_updated = jiffies; - data->valid = 1; -abort: - mutex_unlock(&data->update_lock); - - return ret; -} - -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct max1668_data *data = max1668_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", data->temp[index] * 1000); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct max1668_data *data = max1668_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", data->temp_max[index] * 1000); -} - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct max1668_data *data = max1668_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", data->temp_min[index] * 1000); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct max1668_data *data = max1668_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1); -} - -static ssize_t show_fault(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct max1668_data *data = max1668_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%u\n", - (data->alarms & (1 << 12)) && data->temp[index] == 127); -} - -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct max1668_data *data = i2c_get_clientdata(client); - long temp; - int ret; - - ret = kstrtol(buf, 10, &temp); - if (ret < 0) - return ret; - - mutex_lock(&data->update_lock); - data->temp_max[index] = SENSORS_LIMIT(temp/1000, -128, 127); - if (i2c_smbus_write_byte_data(client, - MAX1668_REG_LIMH_WR(index), - data->temp_max[index])) - count = -EIO; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_temp_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct max1668_data *data = i2c_get_clientdata(client); - long temp; - int ret; - - ret = kstrtol(buf, 10, &temp); - if (ret < 0) - return ret; - - mutex_lock(&data->update_lock); - data->temp_min[index] = SENSORS_LIMIT(temp/1000, -128, 127); - if (i2c_smbus_write_byte_data(client, - MAX1668_REG_LIML_WR(index), - data->temp_max[index])) - count = -EIO; - mutex_unlock(&data->update_lock); - - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, - set_temp_min, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, - set_temp_min, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, - set_temp_max, 2); -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, - set_temp_min, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, - set_temp_max, 3); -static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, - set_temp_min, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, - set_temp_max, 4); -static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, - set_temp_min, 4); - -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 14); -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 13); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 0); - -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_fault, NULL, 4); - -/* Attributes common to MAX1668, MAX1989 and MAX1805 */ -static struct attribute *max1668_attribute_common[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - NULL -}; - -/* Attributes not present on MAX1805 */ -static struct attribute *max1668_attribute_unique[] = { - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_max.dev_attr.attr, - &sensor_dev_attr_temp5_min.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - - &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp5_min_alarm.dev_attr.attr, - - &sensor_dev_attr_temp4_fault.dev_attr.attr, - &sensor_dev_attr_temp5_fault.dev_attr.attr, - NULL -}; - -static umode_t max1668_attribute_mode(struct kobject *kobj, - struct attribute *attr, int index) -{ - umode_t ret = S_IRUGO; - if (read_only) - return ret; - if (attr == &sensor_dev_attr_temp1_max.dev_attr.attr || - attr == &sensor_dev_attr_temp2_max.dev_attr.attr || - attr == &sensor_dev_attr_temp3_max.dev_attr.attr || - attr == &sensor_dev_attr_temp4_max.dev_attr.attr || - attr == &sensor_dev_attr_temp5_max.dev_attr.attr || - attr == &sensor_dev_attr_temp1_min.dev_attr.attr || - attr == &sensor_dev_attr_temp2_min.dev_attr.attr || - attr == &sensor_dev_attr_temp3_min.dev_attr.attr || - attr == &sensor_dev_attr_temp4_min.dev_attr.attr || - attr == &sensor_dev_attr_temp5_min.dev_attr.attr) - ret |= S_IWUSR; - return ret; -} - -static const struct attribute_group max1668_group_common = { - .attrs = max1668_attribute_common, - .is_visible = max1668_attribute_mode -}; - -static const struct attribute_group max1668_group_unique = { - .attrs = max1668_attribute_unique, - .is_visible = max1668_attribute_mode -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max1668_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - const char *type_name; - int man_id, dev_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Check for unsupported part */ - man_id = i2c_smbus_read_byte_data(client, MAX1668_REG_MAN_ID); - if (man_id != MAN_ID_MAXIM) - return -ENODEV; - - dev_id = i2c_smbus_read_byte_data(client, MAX1668_REG_DEV_ID); - if (dev_id < 0) - return -ENODEV; - - type_name = NULL; - if (dev_id == DEV_ID_MAX1668) - type_name = "max1668"; - else if (dev_id == DEV_ID_MAX1805) - type_name = "max1805"; - else if (dev_id == DEV_ID_MAX1989) - type_name = "max1989"; - - if (!type_name) - return -ENODEV; - - strlcpy(info->type, type_name, I2C_NAME_SIZE); - - return 0; -} - -static int max1668_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct max1668_data *data; - int err; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - data = kzalloc(sizeof(struct max1668_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - mutex_init(&data->update_lock); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &max1668_group_common); - if (err) - goto error_free; - - if (data->type == max1668 || data->type == max1989) { - err = sysfs_create_group(&client->dev.kobj, - &max1668_group_unique); - if (err) - goto error_sysrem0; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_sysrem1; - } - - return 0; - -error_sysrem1: - if (data->type == max1668 || data->type == max1989) - sysfs_remove_group(&client->dev.kobj, &max1668_group_unique); -error_sysrem0: - sysfs_remove_group(&client->dev.kobj, &max1668_group_common); -error_free: - kfree(data); - return err; -} - -static int max1668_remove(struct i2c_client *client) -{ - struct max1668_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - if (data->type == max1668 || data->type == max1989) - sysfs_remove_group(&client->dev.kobj, &max1668_group_unique); - - sysfs_remove_group(&client->dev.kobj, &max1668_group_common); - - kfree(data); - return 0; -} - -static const struct i2c_device_id max1668_id[] = { - { "max1668", max1668 }, - { "max1805", max1805 }, - { "max1989", max1989 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max1668_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver max1668_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "max1668", - }, - .probe = max1668_probe, - .remove = max1668_remove, - .id_table = max1668_id, - .detect = max1668_detect, - .address_list = max1668_addr_list, -}; - -module_i2c_driver(max1668_driver); - -MODULE_AUTHOR("David George "); -MODULE_DESCRIPTION("MAX1668 remote temperature sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max6639.c b/ANDROID_3.4.5/drivers/hwmon/max6639.c deleted file mode 100644 index de8f7ada..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max6639.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * max6639.c - Support for Maxim MAX6639 - * - * 2-Channel Temperature Monitor with Dual PWM Fan-Speed Controller - * - * Copyright (C) 2010, 2011 Roland Stigge - * - * based on the initial MAX6639 support from semptian.net - * by He Changqing - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; - -/* The MAX6639 registers, valid channel numbers: 0, 1 */ -#define MAX6639_REG_TEMP(ch) (0x00 + (ch)) -#define MAX6639_REG_STATUS 0x02 -#define MAX6639_REG_OUTPUT_MASK 0x03 -#define MAX6639_REG_GCONFIG 0x04 -#define MAX6639_REG_TEMP_EXT(ch) (0x05 + (ch)) -#define MAX6639_REG_ALERT_LIMIT(ch) (0x08 + (ch)) -#define MAX6639_REG_OT_LIMIT(ch) (0x0A + (ch)) -#define MAX6639_REG_THERM_LIMIT(ch) (0x0C + (ch)) -#define MAX6639_REG_FAN_CONFIG1(ch) (0x10 + (ch) * 4) -#define MAX6639_REG_FAN_CONFIG2a(ch) (0x11 + (ch) * 4) -#define MAX6639_REG_FAN_CONFIG2b(ch) (0x12 + (ch) * 4) -#define MAX6639_REG_FAN_CONFIG3(ch) (0x13 + (ch) * 4) -#define MAX6639_REG_FAN_CNT(ch) (0x20 + (ch)) -#define MAX6639_REG_TARGET_CNT(ch) (0x22 + (ch)) -#define MAX6639_REG_FAN_PPR(ch) (0x24 + (ch)) -#define MAX6639_REG_TARGTDUTY(ch) (0x26 + (ch)) -#define MAX6639_REG_FAN_START_TEMP(ch) (0x28 + (ch)) -#define MAX6639_REG_DEVID 0x3D -#define MAX6639_REG_MANUID 0x3E -#define MAX6639_REG_DEVREV 0x3F - -/* Register bits */ -#define MAX6639_GCONFIG_STANDBY 0x80 -#define MAX6639_GCONFIG_POR 0x40 -#define MAX6639_GCONFIG_DISABLE_TIMEOUT 0x20 -#define MAX6639_GCONFIG_CH2_LOCAL 0x10 -#define MAX6639_GCONFIG_PWM_FREQ_HI 0x08 - -#define MAX6639_FAN_CONFIG1_PWM 0x80 - -#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED 0x40 - -static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 }; - -#define FAN_FROM_REG(val, rpm_range) ((val) == 0 || (val) == 255 ? \ - 0 : (rpm_ranges[rpm_range] * 30) / (val)) -#define TEMP_LIMIT_TO_REG(val) SENSORS_LIMIT((val) / 1000, 0, 255) - -/* - * Client data (each client gets its own) - */ -struct max6639_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* Register values sampled regularly */ - u16 temp[2]; /* Temperature, in 1/8 C, 0..255 C */ - bool temp_fault[2]; /* Detected temperature diode failure */ - u8 fan[2]; /* Register value: TACH count for fans >=30 */ - u8 status; /* Detected channel alarms and fan failures */ - - /* Register values only written to */ - u8 pwm[2]; /* Register value: Duty cycle 0..120 */ - u8 temp_therm[2]; /* THERM Temperature, 0..255 C (->_max) */ - u8 temp_alert[2]; /* ALERT Temperature, 0..255 C (->_crit) */ - u8 temp_ot[2]; /* OT Temperature, 0..255 C (->_emergency) */ - - /* Register values initialized only once */ - u8 ppr; /* Pulses per rotation 0..3 for 1..4 ppr */ - u8 rpm_range; /* Index in above rpm_ranges table */ -}; - -static struct max6639_data *max6639_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct max6639_data *ret = data; - int i; - int status_reg; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - int res; - - dev_dbg(&client->dev, "Starting max6639 update\n"); - - status_reg = i2c_smbus_read_byte_data(client, - MAX6639_REG_STATUS); - if (status_reg < 0) { - ret = ERR_PTR(status_reg); - goto abort; - } - - data->status = status_reg; - - for (i = 0; i < 2; i++) { - res = i2c_smbus_read_byte_data(client, - MAX6639_REG_FAN_CNT(i)); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - data->fan[i] = res; - - res = i2c_smbus_read_byte_data(client, - MAX6639_REG_TEMP_EXT(i)); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - data->temp[i] = res >> 5; - data->temp_fault[i] = res & 0x01; - - res = i2c_smbus_read_byte_data(client, - MAX6639_REG_TEMP(i)); - if (res < 0) { - ret = ERR_PTR(res); - goto abort; - } - data->temp[i] |= res << 3; - } - - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - - return ret; -} - -static ssize_t show_temp_input(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - long temp; - struct max6639_data *data = max6639_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - if (IS_ERR(data)) - return PTR_ERR(data); - - temp = data->temp[attr->index] * 125; - return sprintf(buf, "%ld\n", temp); -} - -static ssize_t show_temp_fault(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct max6639_data *data = max6639_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", data->temp_fault[attr->index]); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000)); -} - -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - unsigned long val; - int res; - - res = kstrtoul(buf, 10, &val); - if (res) - return res; - - mutex_lock(&data->update_lock); - data->temp_therm[attr->index] = TEMP_LIMIT_TO_REG(val); - i2c_smbus_write_byte_data(client, - MAX6639_REG_THERM_LIMIT(attr->index), - data->temp_therm[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_crit(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000)); -} - -static ssize_t set_temp_crit(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - unsigned long val; - int res; - - res = kstrtoul(buf, 10, &val); - if (res) - return res; - - mutex_lock(&data->update_lock); - data->temp_alert[attr->index] = TEMP_LIMIT_TO_REG(val); - i2c_smbus_write_byte_data(client, - MAX6639_REG_ALERT_LIMIT(attr->index), - data->temp_alert[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_emergency(struct device *dev, - struct device_attribute *dev_attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000)); -} - -static ssize_t set_temp_emergency(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - unsigned long val; - int res; - - res = kstrtoul(buf, 10, &val); - if (res) - return res; - - mutex_lock(&data->update_lock); - data->temp_ot[attr->index] = TEMP_LIMIT_TO_REG(val); - i2c_smbus_write_byte_data(client, - MAX6639_REG_OT_LIMIT(attr->index), - data->temp_ot[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_pwm(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120); -} - -static ssize_t set_pwm(struct device *dev, - struct device_attribute *dev_attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6639_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - unsigned long val; - int res; - - res = kstrtoul(buf, 10, &val); - if (res) - return res; - - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - data->pwm[attr->index] = (u8)(val * 120 / 255); - i2c_smbus_write_byte_data(client, - MAX6639_REG_TARGTDUTY(attr->index), - data->pwm[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_fan_input(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct max6639_data *data = max6639_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index], - data->rpm_range)); -} - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct max6639_data *data = max6639_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return sprintf(buf, "%d\n", !!(data->status & (1 << attr->index))); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit, - set_temp_crit, 0); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit, - set_temp_crit, 1); -static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO, - show_temp_emergency, set_temp_emergency, 0); -static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO, - show_temp_emergency, set_temp_emergency, 1); -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 4); - - -static struct attribute *max6639_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp1_emergency.dev_attr.attr, - &sensor_dev_attr_temp2_emergency.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - &sensor_dev_attr_fan2_fault.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group max6639_group = { - .attrs = max6639_attributes, -}; - -/* - * returns respective index in rpm_ranges table - * 1 by default on invalid range - */ -static int rpm_range_to_reg(int range) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(rpm_ranges); i++) { - if (rpm_ranges[i] == range) - return i; - } - - return 1; /* default: 4000 RPM */ -} - -static int max6639_init_client(struct i2c_client *client) -{ - struct max6639_data *data = i2c_get_clientdata(client); - struct max6639_platform_data *max6639_info = - client->dev.platform_data; - int i; - int rpm_range = 1; /* default: 4000 RPM */ - int err; - - /* Reset chip to default values, see below for GCONFIG setup */ - err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG, - MAX6639_GCONFIG_POR); - if (err) - goto exit; - - /* Fans pulse per revolution is 2 by default */ - if (max6639_info && max6639_info->ppr > 0 && - max6639_info->ppr < 5) - data->ppr = max6639_info->ppr; - else - data->ppr = 2; - data->ppr -= 1; - - if (max6639_info) - rpm_range = rpm_range_to_reg(max6639_info->rpm_range); - data->rpm_range = rpm_range; - - for (i = 0; i < 2; i++) { - - /* Set Fan pulse per revolution */ - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_PPR(i), - data->ppr << 6); - if (err) - goto exit; - - /* Fans config PWM, RPM */ - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG1(i), - MAX6639_FAN_CONFIG1_PWM | rpm_range); - if (err) - goto exit; - - /* Fans PWM polarity high by default */ - if (max6639_info && max6639_info->pwm_polarity == 0) - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG2a(i), 0x00); - else - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG2a(i), 0x02); - if (err) - goto exit; - - /* - * /THERM full speed enable, - * PWM frequency 25kHz, see also GCONFIG below - */ - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_FAN_CONFIG3(i), - MAX6639_FAN_CONFIG3_THERM_FULL_SPEED | 0x03); - if (err) - goto exit; - - /* Max. temp. 80C/90C/100C */ - data->temp_therm[i] = 80; - data->temp_alert[i] = 90; - data->temp_ot[i] = 100; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_THERM_LIMIT(i), - data->temp_therm[i]); - if (err) - goto exit; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_ALERT_LIMIT(i), - data->temp_alert[i]); - if (err) - goto exit; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_OT_LIMIT(i), data->temp_ot[i]); - if (err) - goto exit; - - /* PWM 120/120 (i.e. 100%) */ - data->pwm[i] = 120; - err = i2c_smbus_write_byte_data(client, - MAX6639_REG_TARGTDUTY(i), data->pwm[i]); - if (err) - goto exit; - } - /* Start monitoring */ - err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG, - MAX6639_GCONFIG_DISABLE_TIMEOUT | MAX6639_GCONFIG_CH2_LOCAL | - MAX6639_GCONFIG_PWM_FREQ_HI); -exit: - return err; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max6639_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int dev_id, manu_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Actual detection via device and manufacturer ID */ - dev_id = i2c_smbus_read_byte_data(client, MAX6639_REG_DEVID); - manu_id = i2c_smbus_read_byte_data(client, MAX6639_REG_MANUID); - if (dev_id != 0x58 || manu_id != 0x4D) - return -ENODEV; - - strlcpy(info->type, "max6639", I2C_NAME_SIZE); - - return 0; -} - -static int max6639_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max6639_data *data; - int err; - - data = kzalloc(sizeof(struct max6639_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the max6639 chip */ - err = max6639_init_client(client); - if (err < 0) - goto error_free; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &max6639_group); - if (err) - goto error_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_remove; - } - - dev_info(&client->dev, "temperature sensor and fan control found\n"); - - return 0; - -error_remove: - sysfs_remove_group(&client->dev.kobj, &max6639_group); -error_free: - kfree(data); -exit: - return err; -} - -static int max6639_remove(struct i2c_client *client) -{ - struct max6639_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &max6639_group); - - kfree(data); - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int max6639_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG); - if (data < 0) - return data; - - return i2c_smbus_write_byte_data(client, - MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY); -} - -static int max6639_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG); - if (data < 0) - return data; - - return i2c_smbus_write_byte_data(client, - MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY); -} -#endif /* CONFIG_PM_SLEEP */ - -static const struct i2c_device_id max6639_id[] = { - {"max6639", 0}, - { } -}; - -MODULE_DEVICE_TABLE(i2c, max6639_id); - -static const struct dev_pm_ops max6639_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(max6639_suspend, max6639_resume) -}; - -static struct i2c_driver max6639_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "max6639", - .pm = &max6639_pm_ops, - }, - .probe = max6639_probe, - .remove = max6639_remove, - .id_table = max6639_id, - .detect = max6639_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(max6639_driver); - -MODULE_AUTHOR("Roland Stigge "); -MODULE_DESCRIPTION("max6639 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max6642.c b/ANDROID_3.4.5/drivers/hwmon/max6642.c deleted file mode 100644 index 4298909a..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max6642.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Driver for +/-1 degree C, SMBus-Compatible Remote/Local Temperature Sensor - * with Overtemperature Alarm - * - * Copyright (C) 2011 AppearTV AS - * - * Derived from: - * - * Based on the max1619 driver. - * Copyright (C) 2003-2004 Alexey Fisher - * Jean Delvare - * - * The MAX6642 is a sensor chip made by Maxim. - * It reports up to two temperatures (its own plus up to - * one external one). Complete datasheet can be - * obtained from Maxim's website at: - * http://datasheets.maxim-ic.com/en/ds/MAX6642.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static const unsigned short normal_i2c[] = { - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; - -/* - * The MAX6642 registers - */ - -#define MAX6642_REG_R_MAN_ID 0xFE -#define MAX6642_REG_R_CONFIG 0x03 -#define MAX6642_REG_W_CONFIG 0x09 -#define MAX6642_REG_R_STATUS 0x02 -#define MAX6642_REG_R_LOCAL_TEMP 0x00 -#define MAX6642_REG_R_LOCAL_TEMPL 0x11 -#define MAX6642_REG_R_LOCAL_HIGH 0x05 -#define MAX6642_REG_W_LOCAL_HIGH 0x0B -#define MAX6642_REG_R_REMOTE_TEMP 0x01 -#define MAX6642_REG_R_REMOTE_TEMPL 0x10 -#define MAX6642_REG_R_REMOTE_HIGH 0x07 -#define MAX6642_REG_W_REMOTE_HIGH 0x0D - -/* - * Conversions - */ - -static int temp_from_reg10(int val) -{ - return val * 250; -} - -static int temp_from_reg(int val) -{ - return val * 1000; -} - -static int temp_to_reg(int val) -{ - return val / 1000; -} - -/* - * Client data (each client gets its own) - */ - -struct max6642_data { - struct device *hwmon_dev; - struct mutex update_lock; - bool valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - u16 temp_input[2]; /* local/remote */ - u16 temp_high[2]; /* local/remote */ - u8 alarms; -}; - -/* - * Real code - */ - -static void max6642_init_client(struct i2c_client *client) -{ - u8 config; - struct max6642_data *data = i2c_get_clientdata(client); - - /* - * Start the conversions. - */ - config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG); - if (config & 0x40) - i2c_smbus_write_byte_data(client, MAX6642_REG_W_CONFIG, - config & 0xBF); /* run */ - - data->temp_high[0] = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_LOCAL_HIGH); - data->temp_high[1] = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_REMOTE_HIGH); -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int max6642_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u8 reg_config, reg_status, man_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* identification */ - man_id = i2c_smbus_read_byte_data(client, MAX6642_REG_R_MAN_ID); - if (man_id != 0x4D) - return -ENODEV; - - /* sanity check */ - if (i2c_smbus_read_byte_data(client, 0x04) != 0x4D - || i2c_smbus_read_byte_data(client, 0x06) != 0x4D - || i2c_smbus_read_byte_data(client, 0xff) != 0x4D) - return -ENODEV; - - /* - * We read the config and status register, the 4 lower bits in the - * config register should be zero and bit 5, 3, 1 and 0 should be - * zero in the status register. - */ - reg_config = i2c_smbus_read_byte_data(client, MAX6642_REG_R_CONFIG); - if ((reg_config & 0x0f) != 0x00) - return -ENODEV; - - /* in between, another round of sanity checks */ - if (i2c_smbus_read_byte_data(client, 0x04) != reg_config - || i2c_smbus_read_byte_data(client, 0x06) != reg_config - || i2c_smbus_read_byte_data(client, 0xff) != reg_config) - return -ENODEV; - - reg_status = i2c_smbus_read_byte_data(client, MAX6642_REG_R_STATUS); - if ((reg_status & 0x2b) != 0x00) - return -ENODEV; - - strlcpy(info->type, "max6642", I2C_NAME_SIZE); - - return 0; -} - -static struct max6642_data *max6642_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6642_data *data = i2c_get_clientdata(client); - u16 val, tmp; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - dev_dbg(&client->dev, "Updating max6642 data.\n"); - val = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_LOCAL_TEMPL); - tmp = (val >> 6) & 3; - val = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_LOCAL_TEMP); - val = (val << 2) | tmp; - data->temp_input[0] = val; - val = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_REMOTE_TEMPL); - tmp = (val >> 6) & 3; - val = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_REMOTE_TEMP); - val = (val << 2) | tmp; - data->temp_input[1] = val; - data->alarms = i2c_smbus_read_byte_data(client, - MAX6642_REG_R_STATUS); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * Sysfs stuff - */ - -static ssize_t show_temp_max10(struct device *dev, - struct device_attribute *dev_attr, char *buf) -{ - struct max6642_data *data = max6642_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); - - return sprintf(buf, "%d\n", - temp_from_reg10(data->temp_input[attr->index])); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct max6642_data *data = max6642_update_device(dev); - struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); - - return sprintf(buf, "%d\n", temp_from_reg(data->temp_high[attr2->nr])); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long val; - int err; - struct i2c_client *client = to_i2c_client(dev); - struct max6642_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - mutex_lock(&data->update_lock); - data->temp_high[attr2->nr] = SENSORS_LIMIT(temp_to_reg(val), 0, 255); - i2c_smbus_write_byte_data(client, attr2->index, - data->temp_high[attr2->nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct max6642_data *data = max6642_update_device(dev); - return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_max10, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_max10, NULL, 1); -static SENSOR_DEVICE_ATTR_2(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 0, MAX6642_REG_W_LOCAL_HIGH); -static SENSOR_DEVICE_ATTR_2(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - set_temp_max, 1, MAX6642_REG_W_REMOTE_HIGH); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); - -static struct attribute *max6642_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group max6642_group = { - .attrs = max6642_attributes, -}; - -static int max6642_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct max6642_data *data; - int err; - - data = kzalloc(sizeof(struct max6642_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - mutex_init(&data->update_lock); - - /* Initialize the MAX6642 chip */ - max6642_init_client(new_client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &max6642_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &max6642_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int max6642_remove(struct i2c_client *client) -{ - struct max6642_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &max6642_group); - - kfree(data); - return 0; -} - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id max6642_id[] = { - { "max6642", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max6642_id); - -static struct i2c_driver max6642_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "max6642", - }, - .probe = max6642_probe, - .remove = max6642_remove, - .id_table = max6642_id, - .detect = max6642_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(max6642_driver); - -MODULE_AUTHOR("Per Dalen "); -MODULE_DESCRIPTION("MAX6642 sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/max6650.c b/ANDROID_3.4.5/drivers/hwmon/max6650.c deleted file mode 100644 index 33a8a7f1..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/max6650.c +++ /dev/null @@ -1,738 +0,0 @@ -/* - * max6650.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring. - * - * (C) 2007 by Hans J. Koch - * - * based on code written by John Morris - * Copyright (c) 2003 Spirent Communications - * and Claus Gindhart - * - * This module has only been tested with the MAX6650 chip. It should - * also work with the MAX6651. It does not distinguish max6650 and max6651 - * chips. - * - * The datasheet was last seen at: - * - * http://pdfserv.maxim-ic.com/en/ds/MAX6650-MAX6651.pdf - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Insmod parameters - */ - -/* fan_voltage: 5=5V fan, 12=12V fan, 0=don't change */ -static int fan_voltage; -/* prescaler: Possible values are 1, 2, 4, 8, 16 or 0 for don't change */ -static int prescaler; -/* clock: The clock frequency of the chip the driver should assume */ -static int clock = 254000; - -module_param(fan_voltage, int, S_IRUGO); -module_param(prescaler, int, S_IRUGO); -module_param(clock, int, S_IRUGO); - -/* - * MAX 6650/6651 registers - */ - -#define MAX6650_REG_SPEED 0x00 -#define MAX6650_REG_CONFIG 0x02 -#define MAX6650_REG_GPIO_DEF 0x04 -#define MAX6650_REG_DAC 0x06 -#define MAX6650_REG_ALARM_EN 0x08 -#define MAX6650_REG_ALARM 0x0A -#define MAX6650_REG_TACH0 0x0C -#define MAX6650_REG_TACH1 0x0E -#define MAX6650_REG_TACH2 0x10 -#define MAX6650_REG_TACH3 0x12 -#define MAX6650_REG_GPIO_STAT 0x14 -#define MAX6650_REG_COUNT 0x16 - -/* - * Config register bits - */ - -#define MAX6650_CFG_V12 0x08 -#define MAX6650_CFG_PRESCALER_MASK 0x07 -#define MAX6650_CFG_PRESCALER_2 0x01 -#define MAX6650_CFG_PRESCALER_4 0x02 -#define MAX6650_CFG_PRESCALER_8 0x03 -#define MAX6650_CFG_PRESCALER_16 0x04 -#define MAX6650_CFG_MODE_MASK 0x30 -#define MAX6650_CFG_MODE_ON 0x00 -#define MAX6650_CFG_MODE_OFF 0x10 -#define MAX6650_CFG_MODE_CLOSED_LOOP 0x20 -#define MAX6650_CFG_MODE_OPEN_LOOP 0x30 -#define MAX6650_COUNT_MASK 0x03 - -/* - * Alarm status register bits - */ - -#define MAX6650_ALRM_MAX 0x01 -#define MAX6650_ALRM_MIN 0x02 -#define MAX6650_ALRM_TACH 0x04 -#define MAX6650_ALRM_GPIO1 0x08 -#define MAX6650_ALRM_GPIO2 0x10 - -/* Minimum and maximum values of the FAN-RPM */ -#define FAN_RPM_MIN 240 -#define FAN_RPM_MAX 30000 - -#define DIV_FROM_REG(reg) (1 << (reg & 7)) - -static int max6650_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int max6650_init_client(struct i2c_client *client); -static int max6650_remove(struct i2c_client *client); -static struct max6650_data *max6650_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id max6650_id[] = { - { "max6650", 1 }, - { "max6651", 4 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, max6650_id); - -static struct i2c_driver max6650_driver = { - .driver = { - .name = "max6650", - }, - .probe = max6650_probe, - .remove = max6650_remove, - .id_table = max6650_id, -}; - -/* - * Client data (each client gets its own) - */ - -struct max6650_data { - struct device *hwmon_dev; - struct mutex update_lock; - int nr_fans; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* register values */ - u8 speed; - u8 config; - u8 tach[4]; - u8 count; - u8 dac; - u8 alarm; -}; - -static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct max6650_data *data = max6650_update_device(dev); - int rpm; - - /* - * Calculation details: - * - * Each tachometer counts over an interval given by the "count" - * register (0.25, 0.5, 1 or 2 seconds). This module assumes - * that the fans produce two pulses per revolution (this seems - * to be the most common). - */ - - rpm = ((data->tach[attr->index] * 120) / DIV_FROM_REG(data->count)); - return sprintf(buf, "%d\n", rpm); -} - -/* - * Set the fan speed to the specified RPM (or read back the RPM setting). - * This works in closed loop mode only. Use pwm1 for open loop speed setting. - * - * The MAX6650/1 will automatically control fan speed when in closed loop - * mode. - * - * Assumptions: - * - * 1) The MAX6650/1 internal 254kHz clock frequency is set correctly. Use - * the clock module parameter if you need to fine tune this. - * - * 2) The prescaler (low three bits of the config register) has already - * been set to an appropriate value. Use the prescaler module parameter - * if your BIOS doesn't initialize the chip properly. - * - * The relevant equations are given on pages 21 and 22 of the datasheet. - * - * From the datasheet, the relevant equation when in regulation is: - * - * [fCLK / (128 x (KTACH + 1))] = 2 x FanSpeed / KSCALE - * - * where: - * - * fCLK is the oscillator frequency (either the 254kHz internal - * oscillator or the externally applied clock) - * - * KTACH is the value in the speed register - * - * FanSpeed is the speed of the fan in rps - * - * KSCALE is the prescaler value (1, 2, 4, 8, or 16) - * - * When reading, we need to solve for FanSpeed. When writing, we need to - * solve for KTACH. - * - * Note: this tachometer is completely separate from the tachometers - * used to measure the fan speeds. Only one fan's speed (fan1) is - * controlled. - */ - -static ssize_t get_target(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct max6650_data *data = max6650_update_device(dev); - int kscale, ktach, rpm; - - /* - * Use the datasheet equation: - * - * FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)] - * - * then multiply by 60 to give rpm. - */ - - kscale = DIV_FROM_REG(data->config); - ktach = data->speed; - rpm = 60 * kscale * clock / (256 * (ktach + 1)); - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t set_target(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - int kscale, ktach; - unsigned long rpm; - int err; - - err = kstrtoul(buf, 10, &rpm); - if (err) - return err; - - rpm = SENSORS_LIMIT(rpm, FAN_RPM_MIN, FAN_RPM_MAX); - - /* - * Divide the required speed by 60 to get from rpm to rps, then - * use the datasheet equation: - * - * KTACH = [(fCLK x KSCALE) / (256 x FanSpeed)] - 1 - */ - - mutex_lock(&data->update_lock); - - kscale = DIV_FROM_REG(data->config); - ktach = ((clock * kscale) / (256 * rpm / 60)) - 1; - if (ktach < 0) - ktach = 0; - if (ktach > 255) - ktach = 255; - data->speed = ktach; - - i2c_smbus_write_byte_data(client, MAX6650_REG_SPEED, data->speed); - - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Get/set the fan speed in open loop mode using pwm1 sysfs file. - * Speed is given as a relative value from 0 to 255, where 255 is maximum - * speed. Note that this is done by writing directly to the chip's DAC, - * it won't change the closed loop speed set by fan1_target. - * Also note that due to rounding errors it is possible that you don't read - * back exactly the value you have set. - */ - -static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - int pwm; - struct max6650_data *data = max6650_update_device(dev); - - /* - * Useful range for dac is 0-180 for 12V fans and 0-76 for 5V fans. - * Lower DAC values mean higher speeds. - */ - if (data->config & MAX6650_CFG_V12) - pwm = 255 - (255 * (int)data->dac)/180; - else - pwm = 255 - (255 * (int)data->dac)/76; - - if (pwm < 0) - pwm = 0; - - return sprintf(buf, "%d\n", pwm); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - unsigned long pwm; - int err; - - err = kstrtoul(buf, 10, &pwm); - if (err) - return err; - - pwm = SENSORS_LIMIT(pwm, 0, 255); - - mutex_lock(&data->update_lock); - - if (data->config & MAX6650_CFG_V12) - data->dac = 180 - (180 * pwm)/255; - else - data->dac = 76 - (76 * pwm)/255; - - i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, data->dac); - - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Get/Set controller mode: - * Possible values: - * 0 = Fan always on - * 1 = Open loop, Voltage is set according to speed, not regulated. - * 2 = Closed loop, RPM for all fans regulated by fan1 tachometer - */ - -static ssize_t get_enable(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct max6650_data *data = max6650_update_device(dev); - int mode = (data->config & MAX6650_CFG_MODE_MASK) >> 4; - int sysfs_modes[4] = {0, 1, 2, 1}; - - return sprintf(buf, "%d\n", sysfs_modes[mode]); -} - -static ssize_t set_enable(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - int max6650_modes[3] = {0, 3, 2}; - unsigned long mode; - int err; - - err = kstrtoul(buf, 10, &mode); - if (err) - return err; - - if (mode > 2) - return -EINVAL; - - mutex_lock(&data->update_lock); - - data->config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); - data->config = (data->config & ~MAX6650_CFG_MODE_MASK) - | (max6650_modes[mode] << 4); - - i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, data->config); - - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Read/write functions for fan1_div sysfs file. The MAX6650 has no such - * divider. We handle this by converting between divider and counttime: - * - * (counttime == k) <==> (divider == 2^k), k = 0, 1, 2, or 3 - * - * Lower values of k allow to connect a faster fan without the risk of - * counter overflow. The price is lower resolution. You can also set counttime - * using the module parameter. Note that the module parameter "prescaler" also - * influences the behaviour. Unfortunately, there's no sysfs attribute - * defined for that. See the data sheet for details. - */ - -static ssize_t get_div(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct max6650_data *data = max6650_update_device(dev); - - return sprintf(buf, "%d\n", DIV_FROM_REG(data->count)); -} - -static ssize_t set_div(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - unsigned long div; - int err; - - err = kstrtoul(buf, 10, &div); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (div) { - case 1: - data->count = 0; - break; - case 2: - data->count = 1; - break; - case 4: - data->count = 2; - break; - case 8: - data->count = 3; - break; - default: - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - i2c_smbus_write_byte_data(client, MAX6650_REG_COUNT, data->count); - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Get alarm stati: - * Possible values: - * 0 = no alarm - * 1 = alarm - */ - -static ssize_t get_alarm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct max6650_data *data = max6650_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); - int alarm = 0; - - if (data->alarm & attr->index) { - mutex_lock(&data->update_lock); - alarm = 1; - data->alarm &= ~attr->index; - data->alarm |= i2c_smbus_read_byte_data(client, - MAX6650_REG_ALARM); - mutex_unlock(&data->update_lock); - } - - return sprintf(buf, "%d\n", alarm); -} - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, get_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, get_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, get_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, get_fan, NULL, 3); -static DEVICE_ATTR(fan1_target, S_IWUSR | S_IRUGO, get_target, set_target); -static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, get_div, set_div); -static DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, get_enable, set_enable); -static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); -static SENSOR_DEVICE_ATTR(fan1_max_alarm, S_IRUGO, get_alarm, NULL, - MAX6650_ALRM_MAX); -static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, get_alarm, NULL, - MAX6650_ALRM_MIN); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, get_alarm, NULL, - MAX6650_ALRM_TACH); -static SENSOR_DEVICE_ATTR(gpio1_alarm, S_IRUGO, get_alarm, NULL, - MAX6650_ALRM_GPIO1); -static SENSOR_DEVICE_ATTR(gpio2_alarm, S_IRUGO, get_alarm, NULL, - MAX6650_ALRM_GPIO2); - -static umode_t max6650_attrs_visible(struct kobject *kobj, struct attribute *a, - int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct i2c_client *client = to_i2c_client(dev); - u8 alarm_en = i2c_smbus_read_byte_data(client, MAX6650_REG_ALARM_EN); - struct device_attribute *devattr; - - /* - * Hide the alarms that have not been enabled by the firmware - */ - - devattr = container_of(a, struct device_attribute, attr); - if (devattr == &sensor_dev_attr_fan1_max_alarm.dev_attr - || devattr == &sensor_dev_attr_fan1_min_alarm.dev_attr - || devattr == &sensor_dev_attr_fan1_fault.dev_attr - || devattr == &sensor_dev_attr_gpio1_alarm.dev_attr - || devattr == &sensor_dev_attr_gpio2_alarm.dev_attr) { - if (!(alarm_en & to_sensor_dev_attr(devattr)->index)) - return 0; - } - - return a->mode; -} - -static struct attribute *max6650_attrs[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &dev_attr_fan1_target.attr, - &dev_attr_fan1_div.attr, - &dev_attr_pwm1_enable.attr, - &dev_attr_pwm1.attr, - &sensor_dev_attr_fan1_max_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_min_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - &sensor_dev_attr_gpio1_alarm.dev_attr.attr, - &sensor_dev_attr_gpio2_alarm.dev_attr.attr, - NULL -}; - -static struct attribute_group max6650_attr_grp = { - .attrs = max6650_attrs, - .is_visible = max6650_attrs_visible, -}; - -static struct attribute *max6651_attrs[] = { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group max6651_attr_grp = { - .attrs = max6651_attrs, -}; - -/* - * Real code - */ - -static int max6650_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max6650_data *data; - int err; - - data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "out of memory.\n"); - return -ENOMEM; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->nr_fans = id->driver_data; - - /* - * Initialize the max6650 chip - */ - err = max6650_init_client(client); - if (err) - goto err_free; - - err = sysfs_create_group(&client->dev.kobj, &max6650_attr_grp); - if (err) - goto err_free; - /* 3 additional fan inputs for the MAX6651 */ - if (data->nr_fans == 4) { - err = sysfs_create_group(&client->dev.kobj, &max6651_attr_grp); - if (err) - goto err_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; - - err = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "error registering hwmon device.\n"); - if (data->nr_fans == 4) - sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); -err_remove: - sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); -err_free: - kfree(data); - return err; -} - -static int max6650_remove(struct i2c_client *client) -{ - struct max6650_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - if (data->nr_fans == 4) - sysfs_remove_group(&client->dev.kobj, &max6651_attr_grp); - sysfs_remove_group(&client->dev.kobj, &max6650_attr_grp); - kfree(data); - return 0; -} - -static int max6650_init_client(struct i2c_client *client) -{ - struct max6650_data *data = i2c_get_clientdata(client); - int config; - int err = -EIO; - - config = i2c_smbus_read_byte_data(client, MAX6650_REG_CONFIG); - - if (config < 0) { - dev_err(&client->dev, "Error reading config, aborting.\n"); - return err; - } - - switch (fan_voltage) { - case 0: - break; - case 5: - config &= ~MAX6650_CFG_V12; - break; - case 12: - config |= MAX6650_CFG_V12; - break; - default: - dev_err(&client->dev, "illegal value for fan_voltage (%d)\n", - fan_voltage); - } - - dev_info(&client->dev, "Fan voltage is set to %dV.\n", - (config & MAX6650_CFG_V12) ? 12 : 5); - - switch (prescaler) { - case 0: - break; - case 1: - config &= ~MAX6650_CFG_PRESCALER_MASK; - break; - case 2: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_2; - break; - case 4: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_4; - break; - case 8: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_8; - break; - case 16: - config = (config & ~MAX6650_CFG_PRESCALER_MASK) - | MAX6650_CFG_PRESCALER_16; - break; - default: - dev_err(&client->dev, "illegal value for prescaler (%d)\n", - prescaler); - } - - dev_info(&client->dev, "Prescaler is set to %d.\n", - 1 << (config & MAX6650_CFG_PRESCALER_MASK)); - - /* - * If mode is set to "full off", we change it to "open loop" and - * set DAC to 255, which has the same effect. We do this because - * there's no "full off" mode defined in hwmon specifcations. - */ - - if ((config & MAX6650_CFG_MODE_MASK) == MAX6650_CFG_MODE_OFF) { - dev_dbg(&client->dev, "Change mode to open loop, full off.\n"); - config = (config & ~MAX6650_CFG_MODE_MASK) - | MAX6650_CFG_MODE_OPEN_LOOP; - if (i2c_smbus_write_byte_data(client, MAX6650_REG_DAC, 255)) { - dev_err(&client->dev, "DAC write error, aborting.\n"); - return err; - } - } - - if (i2c_smbus_write_byte_data(client, MAX6650_REG_CONFIG, config)) { - dev_err(&client->dev, "Config write error, aborting.\n"); - return err; - } - - data->config = config; - data->count = i2c_smbus_read_byte_data(client, MAX6650_REG_COUNT); - - return 0; -} - -static const u8 tach_reg[] = { - MAX6650_REG_TACH0, - MAX6650_REG_TACH1, - MAX6650_REG_TACH2, - MAX6650_REG_TACH3, -}; - -static struct max6650_data *max6650_update_device(struct device *dev) -{ - int i; - struct i2c_client *client = to_i2c_client(dev); - struct max6650_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - data->speed = i2c_smbus_read_byte_data(client, - MAX6650_REG_SPEED); - data->config = i2c_smbus_read_byte_data(client, - MAX6650_REG_CONFIG); - for (i = 0; i < data->nr_fans; i++) { - data->tach[i] = i2c_smbus_read_byte_data(client, - tach_reg[i]); - } - data->count = i2c_smbus_read_byte_data(client, - MAX6650_REG_COUNT); - data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC); - - /* - * Alarms are cleared on read in case the condition that - * caused the alarm is removed. Keep the value latched here - * for providing the register through different alarm files. - */ - data->alarm |= i2c_smbus_read_byte_data(client, - MAX6650_REG_ALARM); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(max6650_driver); - -MODULE_AUTHOR("Hans J. Koch"); -MODULE_DESCRIPTION("MAX6650 sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/mc13783-adc.c b/ANDROID_3.4.5/drivers/hwmon/mc13783-adc.c deleted file mode 100644 index ce86c5e3..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/mc13783-adc.c +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Driver for the ADC on Freescale Semiconductor MC13783 and MC13892 PMICs. - * - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2009 Sascha Hauer, Pengutronix - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "mc13783-adc" - -/* platform device id driver data */ -#define MC13783_ADC_16CHANS 1 -#define MC13783_ADC_BPDIV2 2 - -struct mc13783_adc_priv { - struct mc13xxx *mc13xxx; - struct device *hwmon_dev; - char name[10]; -}; - -static ssize_t mc13783_adc_show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct mc13783_adc_priv *priv = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", priv->name); -} - -static int mc13783_adc_read(struct device *dev, - struct device_attribute *devattr, unsigned int *val) -{ - struct mc13783_adc_priv *priv = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - unsigned int channel = attr->index; - unsigned int sample[4]; - int ret; - - ret = mc13xxx_adc_do_conversion(priv->mc13xxx, - MC13XXX_ADC_MODE_MULT_CHAN, - channel, 0, 0, sample); - if (ret) - return ret; - - channel &= 0x7; - - *val = (sample[channel % 4] >> (channel > 3 ? 14 : 2)) & 0x3ff; - - return 0; -} - -static ssize_t mc13783_adc_read_bp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - unsigned val; - struct platform_device *pdev = to_platform_device(dev); - kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data; - int ret = mc13783_adc_read(dev, devattr, &val); - - if (ret) - return ret; - - if (driver_data & MC13783_ADC_BPDIV2) - val = DIV_ROUND_CLOSEST(val * 9, 2); - else - /* - * BP (channel 2) reports with offset 2.4V to the actual value - * to fit the input range of the ADC. unit = 2.25mV = 9/4 mV. - */ - val = DIV_ROUND_CLOSEST(val * 9, 4) + 2400; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t mc13783_adc_read_gp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - unsigned val; - int ret = mc13783_adc_read(dev, devattr, &val); - - if (ret) - return ret; - - /* - * input range is [0, 2.3V], val has 10 bits, so each bit - * is worth 9/4 mV. - */ - val = DIV_ROUND_CLOSEST(val * 9, 4); - - return sprintf(buf, "%u\n", val); -} - -static DEVICE_ATTR(name, S_IRUGO, mc13783_adc_show_name, NULL); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, mc13783_adc_read_bp, NULL, 2); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, mc13783_adc_read_gp, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, mc13783_adc_read_gp, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, mc13783_adc_read_gp, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, mc13783_adc_read_gp, NULL, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, mc13783_adc_read_gp, NULL, 9); -static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, mc13783_adc_read_gp, NULL, 10); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, mc13783_adc_read_gp, NULL, 11); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, mc13783_adc_read_gp, NULL, 12); -static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, mc13783_adc_read_gp, NULL, 13); -static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, mc13783_adc_read_gp, NULL, 14); -static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, mc13783_adc_read_gp, NULL, 15); - -static struct attribute *mc13783_attr_base[] = { - &dev_attr_name.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group mc13783_group_base = { - .attrs = mc13783_attr_base, -}; - -/* these are only used if MC13783_ADC_16CHANS is provided in driver data */ -static struct attribute *mc13783_attr_16chans[] = { - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_in10_input.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group mc13783_group_16chans = { - .attrs = mc13783_attr_16chans, -}; - -/* last four channels may be occupied by the touchscreen */ -static struct attribute *mc13783_attr_ts[] = { - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_in13_input.dev_attr.attr, - &sensor_dev_attr_in14_input.dev_attr.attr, - &sensor_dev_attr_in15_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group mc13783_group_ts = { - .attrs = mc13783_attr_ts, -}; - -static int mc13783_adc_use_touchscreen(struct platform_device *pdev) -{ - struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); - unsigned flags = mc13xxx_get_flags(priv->mc13xxx); - - return flags & MC13XXX_USE_TOUCHSCREEN; -} - -static int __init mc13783_adc_probe(struct platform_device *pdev) -{ - struct mc13783_adc_priv *priv; - int ret; - const struct platform_device_id *id = platform_get_device_id(pdev); - char *dash; - - priv = kzalloc(sizeof(*priv), GFP_KERNEL); - if (!priv) - return -ENOMEM; - - priv->mc13xxx = dev_get_drvdata(pdev->dev.parent); - snprintf(priv->name, ARRAY_SIZE(priv->name), "%s", id->name); - dash = strchr(priv->name, '-'); - if (dash) - *dash = '\0'; - - platform_set_drvdata(pdev, priv); - - /* Register sysfs hooks */ - ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_base); - if (ret) - goto out_err_create_base; - - if (id->driver_data & MC13783_ADC_16CHANS) { - ret = sysfs_create_group(&pdev->dev.kobj, - &mc13783_group_16chans); - if (ret) - goto out_err_create_16chans; - } - - if (!mc13783_adc_use_touchscreen(pdev)) { - ret = sysfs_create_group(&pdev->dev.kobj, &mc13783_group_ts); - if (ret) - goto out_err_create_ts; - } - - priv->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(priv->hwmon_dev)) { - ret = PTR_ERR(priv->hwmon_dev); - dev_err(&pdev->dev, - "hwmon_device_register failed with %d.\n", ret); - goto out_err_register; - } - - return 0; - -out_err_register: - - if (!mc13783_adc_use_touchscreen(pdev)) - sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); -out_err_create_ts: - - if (id->driver_data & MC13783_ADC_16CHANS) - sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans); -out_err_create_16chans: - - sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base); -out_err_create_base: - - platform_set_drvdata(pdev, NULL); - kfree(priv); - - return ret; -} - -static int __devexit mc13783_adc_remove(struct platform_device *pdev) -{ - struct mc13783_adc_priv *priv = platform_get_drvdata(pdev); - kernel_ulong_t driver_data = platform_get_device_id(pdev)->driver_data; - - hwmon_device_unregister(priv->hwmon_dev); - - if (!mc13783_adc_use_touchscreen(pdev)) - sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_ts); - - if (driver_data & MC13783_ADC_16CHANS) - sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_16chans); - - sysfs_remove_group(&pdev->dev.kobj, &mc13783_group_base); - - platform_set_drvdata(pdev, NULL); - kfree(priv); - - return 0; -} - -static const struct platform_device_id mc13783_adc_idtable[] = { - { - .name = "mc13783-adc", - .driver_data = MC13783_ADC_16CHANS, - }, { - .name = "mc13892-adc", - .driver_data = MC13783_ADC_BPDIV2, - }, { - /* sentinel */ - } -}; -MODULE_DEVICE_TABLE(platform, mc13783_adc_idtable); - -static struct platform_driver mc13783_adc_driver = { - .remove = __devexit_p(mc13783_adc_remove), - .driver = { - .owner = THIS_MODULE, - .name = DRIVER_NAME, - }, - .id_table = mc13783_adc_idtable, -}; - -static int __init mc13783_adc_init(void) -{ - return platform_driver_probe(&mc13783_adc_driver, mc13783_adc_probe); -} - -static void __exit mc13783_adc_exit(void) -{ - platform_driver_unregister(&mc13783_adc_driver); -} - -module_init(mc13783_adc_init); -module_exit(mc13783_adc_exit); - -MODULE_DESCRIPTION("MC13783 ADC driver"); -MODULE_AUTHOR("Luotao Fu "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/mcp3021.c b/ANDROID_3.4.5/drivers/hwmon/mcp3021.c deleted file mode 100644 index d0afc0cd..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/mcp3021.c +++ /dev/null @@ -1,171 +0,0 @@ -/* - * mcp3021.c - driver for the Microchip MCP3021 chip - * - * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc. - * Author: Mingkai Hu - * - * This driver export the value of analog input voltage to sysfs, the - * voltage unit is mV. Through the sysfs interface, lm-sensors tool - * can also display the input voltage. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include - -/* Vdd info */ -#define MCP3021_VDD_MAX 5500 -#define MCP3021_VDD_MIN 2700 -#define MCP3021_VDD_REF 3300 - -/* output format */ -#define MCP3021_SAR_SHIFT 2 -#define MCP3021_SAR_MASK 0x3ff - -#define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */ -#define MCP3021_OUTPUT_SCALE 4 - -/* - * Client data (each client gets its own) - */ -struct mcp3021_data { - struct device *hwmon_dev; - u32 vdd; /* device power supply */ -}; - -static int mcp3021_read16(struct i2c_client *client) -{ - int ret; - u16 reg; - __be16 buf; - - ret = i2c_master_recv(client, (char *)&buf, 2); - if (ret < 0) - return ret; - if (ret != 2) - return -EIO; - - /* The output code of the MCP3021 is transmitted with MSB first. */ - reg = be16_to_cpu(buf); - - /* - * The ten-bit output code is composed of the lower 4-bit of the - * first byte and the upper 6-bit of the second byte. - */ - reg = (reg >> MCP3021_SAR_SHIFT) & MCP3021_SAR_MASK; - - return reg; -} - -static inline u16 volts_from_reg(u16 vdd, u16 val) -{ - if (val == 0) - return 0; - - val = val * MCP3021_OUTPUT_SCALE - MCP3021_OUTPUT_SCALE / 2; - - return val * DIV_ROUND_CLOSEST(vdd, - (1 << MCP3021_OUTPUT_RES) * MCP3021_OUTPUT_SCALE); -} - -static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct mcp3021_data *data = i2c_get_clientdata(client); - int reg, in_input; - - reg = mcp3021_read16(client); - if (reg < 0) - return reg; - - in_input = volts_from_reg(data->vdd, reg); - return sprintf(buf, "%d\n", in_input); -} - -static DEVICE_ATTR(in0_input, S_IRUGO, show_in_input, NULL); - -static int mcp3021_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int err; - struct mcp3021_data *data = NULL; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) - return -ENODEV; - - data = kzalloc(sizeof(struct mcp3021_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - - if (client->dev.platform_data) { - data->vdd = *(u32 *)client->dev.platform_data; - if (data->vdd > MCP3021_VDD_MAX || - data->vdd < MCP3021_VDD_MIN) { - err = -EINVAL; - goto exit_free; - } - } else - data->vdd = MCP3021_VDD_REF; - - err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr); -exit_free: - kfree(data); - return err; -} - -static int mcp3021_remove(struct i2c_client *client) -{ - struct mcp3021_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr); - kfree(data); - - return 0; -} - -static const struct i2c_device_id mcp3021_id[] = { - { "mcp3021", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, mcp3021_id); - -static struct i2c_driver mcp3021_driver = { - .driver = { - .name = "mcp3021", - }, - .probe = mcp3021_probe, - .remove = mcp3021_remove, - .id_table = mcp3021_id, -}; - -module_i2c_driver(mcp3021_driver); - -MODULE_AUTHOR("Mingkai Hu "); -MODULE_DESCRIPTION("Microchip MCP3021 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ntc_thermistor.c b/ANDROID_3.4.5/drivers/hwmon/ntc_thermistor.c deleted file mode 100644 index 9b382ec2..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ntc_thermistor.c +++ /dev/null @@ -1,440 +0,0 @@ -/* - * ntc_thermistor.c - NTC Thermistors - * - * Copyright (C) 2010 Samsung Electronics - * MyungJoo Ham - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ - -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -struct ntc_compensation { - int temp_C; - unsigned int ohm; -}; - -/* - * A compensation table should be sorted by the values of .ohm - * in descending order. - * The following compensation tables are from the specification of Murata NTC - * Thermistors Datasheet - */ -const struct ntc_compensation ncpXXwb473[] = { - { .temp_C = -40, .ohm = 1747920 }, - { .temp_C = -35, .ohm = 1245428 }, - { .temp_C = -30, .ohm = 898485 }, - { .temp_C = -25, .ohm = 655802 }, - { .temp_C = -20, .ohm = 483954 }, - { .temp_C = -15, .ohm = 360850 }, - { .temp_C = -10, .ohm = 271697 }, - { .temp_C = -5, .ohm = 206463 }, - { .temp_C = 0, .ohm = 158214 }, - { .temp_C = 5, .ohm = 122259 }, - { .temp_C = 10, .ohm = 95227 }, - { .temp_C = 15, .ohm = 74730 }, - { .temp_C = 20, .ohm = 59065 }, - { .temp_C = 25, .ohm = 47000 }, - { .temp_C = 30, .ohm = 37643 }, - { .temp_C = 35, .ohm = 30334 }, - { .temp_C = 40, .ohm = 24591 }, - { .temp_C = 45, .ohm = 20048 }, - { .temp_C = 50, .ohm = 16433 }, - { .temp_C = 55, .ohm = 13539 }, - { .temp_C = 60, .ohm = 11209 }, - { .temp_C = 65, .ohm = 9328 }, - { .temp_C = 70, .ohm = 7798 }, - { .temp_C = 75, .ohm = 6544 }, - { .temp_C = 80, .ohm = 5518 }, - { .temp_C = 85, .ohm = 4674 }, - { .temp_C = 90, .ohm = 3972 }, - { .temp_C = 95, .ohm = 3388 }, - { .temp_C = 100, .ohm = 2902 }, - { .temp_C = 105, .ohm = 2494 }, - { .temp_C = 110, .ohm = 2150 }, - { .temp_C = 115, .ohm = 1860 }, - { .temp_C = 120, .ohm = 1615 }, - { .temp_C = 125, .ohm = 1406 }, -}; -const struct ntc_compensation ncpXXwl333[] = { - { .temp_C = -40, .ohm = 1610154 }, - { .temp_C = -35, .ohm = 1130850 }, - { .temp_C = -30, .ohm = 802609 }, - { .temp_C = -25, .ohm = 575385 }, - { .temp_C = -20, .ohm = 416464 }, - { .temp_C = -15, .ohm = 304219 }, - { .temp_C = -10, .ohm = 224193 }, - { .temp_C = -5, .ohm = 166623 }, - { .temp_C = 0, .ohm = 124850 }, - { .temp_C = 5, .ohm = 94287 }, - { .temp_C = 10, .ohm = 71747 }, - { .temp_C = 15, .ohm = 54996 }, - { .temp_C = 20, .ohm = 42455 }, - { .temp_C = 25, .ohm = 33000 }, - { .temp_C = 30, .ohm = 25822 }, - { .temp_C = 35, .ohm = 20335 }, - { .temp_C = 40, .ohm = 16115 }, - { .temp_C = 45, .ohm = 12849 }, - { .temp_C = 50, .ohm = 10306 }, - { .temp_C = 55, .ohm = 8314 }, - { .temp_C = 60, .ohm = 6746 }, - { .temp_C = 65, .ohm = 5503 }, - { .temp_C = 70, .ohm = 4513 }, - { .temp_C = 75, .ohm = 3721 }, - { .temp_C = 80, .ohm = 3084 }, - { .temp_C = 85, .ohm = 2569 }, - { .temp_C = 90, .ohm = 2151 }, - { .temp_C = 95, .ohm = 1809 }, - { .temp_C = 100, .ohm = 1529 }, - { .temp_C = 105, .ohm = 1299 }, - { .temp_C = 110, .ohm = 1108 }, - { .temp_C = 115, .ohm = 949 }, - { .temp_C = 120, .ohm = 817 }, - { .temp_C = 125, .ohm = 707 }, -}; - -struct ntc_data { - struct device *hwmon_dev; - struct ntc_thermistor_platform_data *pdata; - const struct ntc_compensation *comp; - struct device *dev; - int n_comp; - char name[PLATFORM_NAME_SIZE]; -}; - -static inline u64 div64_u64_safe(u64 dividend, u64 divisor) -{ - if (divisor == 0 && dividend == 0) - return 0; - if (divisor == 0) - return UINT_MAX; - return div64_u64(dividend, divisor); -} - -static unsigned int get_ohm_of_thermistor(struct ntc_data *data, - unsigned int uV) -{ - struct ntc_thermistor_platform_data *pdata = data->pdata; - u64 mV = uV / 1000; - u64 pmV = pdata->pullup_uV / 1000; - u64 N, puO, pdO; - puO = pdata->pullup_ohm; - pdO = pdata->pulldown_ohm; - - if (mV == 0) { - if (pdata->connect == NTC_CONNECTED_POSITIVE) - return UINT_MAX; - return 0; - } - if (mV >= pmV) - return (pdata->connect == NTC_CONNECTED_POSITIVE) ? - 0 : UINT_MAX; - - if (pdata->connect == NTC_CONNECTED_POSITIVE && puO == 0) - N = div64_u64_safe(pdO * (pmV - mV), mV); - else if (pdata->connect == NTC_CONNECTED_GROUND && pdO == 0) - N = div64_u64_safe(puO * mV, pmV - mV); - else if (pdata->connect == NTC_CONNECTED_POSITIVE) - N = div64_u64_safe(pdO * puO * (pmV - mV), - puO * mV - pdO * (pmV - mV)); - else - N = div64_u64_safe(pdO * puO * mV, pdO * (pmV - mV) - puO * mV); - - return (unsigned int) N; -} - -static int lookup_comp(struct ntc_data *data, - unsigned int ohm, int *i_low, int *i_high) -{ - int start, end, mid = -1; - - /* Do a binary search on compensation table */ - start = 0; - end = data->n_comp; - - while (end > start) { - mid = start + (end - start) / 2; - if (data->comp[mid].ohm < ohm) - end = mid; - else if (data->comp[mid].ohm > ohm) - start = mid + 1; - else - break; - } - - if (mid == 0) { - if (data->comp[mid].ohm > ohm) { - *i_high = mid; - *i_low = mid + 1; - return 0; - } else { - *i_low = mid; - *i_high = -1; - return -EINVAL; - } - } - if (mid == (data->n_comp - 1)) { - if (data->comp[mid].ohm <= ohm) { - *i_low = mid; - *i_high = mid - 1; - return 0; - } else { - *i_low = -1; - *i_high = mid; - return -EINVAL; - } - } - - if (data->comp[mid].ohm <= ohm) { - *i_low = mid; - *i_high = mid - 1; - } else { - *i_low = mid + 1; - *i_high = mid; - } - - return 0; -} - -static int get_temp_mC(struct ntc_data *data, unsigned int ohm, int *temp) -{ - int low, high; - int ret; - - ret = lookup_comp(data, ohm, &low, &high); - if (ret) { - /* Unable to use linear approximation */ - if (low != -1) - *temp = data->comp[low].temp_C * 1000; - else if (high != -1) - *temp = data->comp[high].temp_C * 1000; - else - return ret; - } else { - *temp = data->comp[low].temp_C * 1000 + - ((data->comp[high].temp_C - data->comp[low].temp_C) * - 1000 * ((int)ohm - (int)data->comp[low].ohm)) / - ((int)data->comp[high].ohm - (int)data->comp[low].ohm); - } - - return 0; -} - -static int ntc_thermistor_read(struct ntc_data *data, int *temp) -{ - int ret; - int read_ohm, read_uV; - unsigned int ohm = 0; - - if (data->pdata->read_ohm) { - read_ohm = data->pdata->read_ohm(); - if (read_ohm < 0) - return read_ohm; - ohm = (unsigned int)read_ohm; - } - - if (data->pdata->read_uV) { - read_uV = data->pdata->read_uV(); - if (read_uV < 0) - return read_uV; - ohm = get_ohm_of_thermistor(data, (unsigned int)read_uV); - } - - ret = get_temp_mC(data, ohm, temp); - if (ret) { - dev_dbg(data->dev, "Sensor reading function not available.\n"); - return ret; - } - - return 0; -} - -static ssize_t ntc_show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ntc_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} - -static ssize_t ntc_show_type(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "4\n"); -} - -static ssize_t ntc_show_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct ntc_data *data = dev_get_drvdata(dev); - int temp, ret; - - ret = ntc_thermistor_read(data, &temp); - if (ret) - return ret; - return sprintf(buf, "%d\n", temp); -} - -static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, ntc_show_type, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, ntc_show_temp, NULL, 0); -static DEVICE_ATTR(name, S_IRUGO, ntc_show_name, NULL); - -static struct attribute *ntc_attributes[] = { - &dev_attr_name.attr, - &sensor_dev_attr_temp1_type.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - NULL, -}; - -static const struct attribute_group ntc_attr_group = { - .attrs = ntc_attributes, -}; - -static int __devinit ntc_thermistor_probe(struct platform_device *pdev) -{ - struct ntc_data *data; - struct ntc_thermistor_platform_data *pdata = pdev->dev.platform_data; - int ret = 0; - - if (!pdata) { - dev_err(&pdev->dev, "No platform init data supplied.\n"); - return -ENODEV; - } - - /* Either one of the two is required. */ - if (!pdata->read_uV && !pdata->read_ohm) { - dev_err(&pdev->dev, "Both read_uV and read_ohm missing." - "Need either one of the two.\n"); - return -EINVAL; - } - - if (pdata->read_uV && pdata->read_ohm) { - dev_warn(&pdev->dev, "Only one of read_uV and read_ohm " - "is needed; ignoring read_uV.\n"); - pdata->read_uV = NULL; - } - - if (pdata->read_uV && (pdata->pullup_uV == 0 || - (pdata->pullup_ohm == 0 && pdata->connect == - NTC_CONNECTED_GROUND) || - (pdata->pulldown_ohm == 0 && pdata->connect == - NTC_CONNECTED_POSITIVE) || - (pdata->connect != NTC_CONNECTED_POSITIVE && - pdata->connect != NTC_CONNECTED_GROUND))) { - dev_err(&pdev->dev, "Required data to use read_uV not " - "supplied.\n"); - return -EINVAL; - } - - data = kzalloc(sizeof(struct ntc_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->dev = &pdev->dev; - data->pdata = pdata; - strncpy(data->name, pdev->id_entry->name, PLATFORM_NAME_SIZE); - - switch (pdev->id_entry->driver_data) { - case TYPE_NCPXXWB473: - data->comp = ncpXXwb473; - data->n_comp = ARRAY_SIZE(ncpXXwb473); - break; - case TYPE_NCPXXWL333: - data->comp = ncpXXwl333; - data->n_comp = ARRAY_SIZE(ncpXXwl333); - break; - default: - dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n", - pdev->id_entry->driver_data, - pdev->id_entry->name); - ret = -EINVAL; - goto err; - } - - platform_set_drvdata(pdev, data); - - ret = sysfs_create_group(&data->dev->kobj, &ntc_attr_group); - if (ret) { - dev_err(data->dev, "unable to create sysfs files\n"); - goto err; - } - - data->hwmon_dev = hwmon_device_register(data->dev); - if (IS_ERR_OR_NULL(data->hwmon_dev)) { - dev_err(data->dev, "unable to register as hwmon device.\n"); - ret = -EINVAL; - goto err_after_sysfs; - } - - dev_info(&pdev->dev, "Thermistor %s:%d (type: %s/%lu) successfully probed.\n", - pdev->name, pdev->id, pdev->id_entry->name, - pdev->id_entry->driver_data); - return 0; -err_after_sysfs: - sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); -err: - kfree(data); - return ret; -} - -static int __devexit ntc_thermistor_remove(struct platform_device *pdev) -{ - struct ntc_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&data->dev->kobj, &ntc_attr_group); - platform_set_drvdata(pdev, NULL); - - kfree(data); - - return 0; -} - -static const struct platform_device_id ntc_thermistor_id[] = { - { "ncp15wb473", TYPE_NCPXXWB473 }, - { "ncp18wb473", TYPE_NCPXXWB473 }, - { "ncp21wb473", TYPE_NCPXXWB473 }, - { "ncp03wb473", TYPE_NCPXXWB473 }, - { "ncp15wl333", TYPE_NCPXXWL333 }, - { }, -}; - -static struct platform_driver ntc_thermistor_driver = { - .driver = { - .name = "ntc-thermistor", - .owner = THIS_MODULE, - }, - .probe = ntc_thermistor_probe, - .remove = __devexit_p(ntc_thermistor_remove), - .id_table = ntc_thermistor_id, -}; - -module_platform_driver(ntc_thermistor_driver); - -MODULE_DESCRIPTION("NTC Thermistor Driver"); -MODULE_AUTHOR("MyungJoo Ham "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:ntc-thermistor"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pc87360.c b/ANDROID_3.4.5/drivers/hwmon/pc87360.c deleted file mode 100644 index 79ba48c8..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pc87360.c +++ /dev/null @@ -1,1832 +0,0 @@ -/* - * pc87360.c - Part of lm_sensors, Linux kernel modules - * for hardware monitoring - * Copyright (C) 2004, 2007 Jean Delvare - * - * Copied from smsc47m1.c: - * Copyright (C) 2002 Mark D. 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 devid - * PC87360 - 2 2 - 0xE1 - * PC87363 - 2 2 - 0xE8 - * PC87364 - 3 3 - 0xE4 - * PC87365 11 3 3 2 0xE5 - * PC87366 11 3 3 3-4 0xE9 - * - * This driver assumes that no more than one chip is present, and one of - * the standard Super-I/O addresses is used (0x2E/0x2F or 0x4E/0x4F). - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static u8 devid; -static struct platform_device *pdev; -static unsigned short extra_isa[3]; -static u8 confreg[4]; - -static int init = 1; -module_param(init, int, 0); -MODULE_PARM_DESC(init, -"Chip initialization level:\n" -" 0: None\n" -"*1: Forcibly enable internal voltage and temperature channels, except in9\n" -" 2: Forcibly enable all voltage and temperature channels, except in9\n" -" 3: Forcibly enable all voltage and temperature channels, including in9"); - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -/* - * Super-I/O registers and operations - */ - -#define DEV 0x07 /* Register: Logical device select */ -#define DEVID 0x20 /* Register: Device ID */ -#define ACT 0x30 /* Register: Device activation */ -#define BASE 0x60 /* Register: Base address */ - -#define FSCM 0x09 /* Logical device: fans */ -#define VLM 0x0d /* Logical device: voltages */ -#define TMS 0x0e /* Logical device: temperatures */ -#define LDNI_MAX 3 -static const u8 logdev[LDNI_MAX] = { FSCM, VLM, TMS }; - -#define LD_FAN 0 -#define LD_IN 1 -#define LD_TEMP 2 - -static inline void superio_outb(int sioaddr, int reg, int val) -{ - outb(reg, sioaddr); - outb(val, sioaddr + 1); -} - -static inline int superio_inb(int sioaddr, int reg) -{ - outb(reg, sioaddr); - return inb(sioaddr + 1); -} - -static inline void superio_exit(int sioaddr) -{ - outb(0x02, sioaddr); - outb(0x02, sioaddr + 1); -} - -/* - * Logical devices - */ - -#define PC87360_EXTENT 0x10 -#define PC87365_REG_BANK 0x09 -#define NO_BANK 0xff - -/* - * Fan registers and conversions - */ - -/* nr has to be 0 or 1 (PC87360/87363) or 2 (PC87364/87365/87366) */ -#define PC87360_REG_PRESCALE(nr) (0x00 + 2 * (nr)) -#define PC87360_REG_PWM(nr) (0x01 + 2 * (nr)) -#define PC87360_REG_FAN_MIN(nr) (0x06 + 3 * (nr)) -#define PC87360_REG_FAN(nr) (0x07 + 3 * (nr)) -#define PC87360_REG_FAN_STATUS(nr) (0x08 + 3 * (nr)) - -#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : \ - 480000 / ((val) * (div))) -#define FAN_TO_REG(val, div) ((val) <= 100 ? 0 : \ - 480000 / ((val) * (div))) -#define FAN_DIV_FROM_REG(val) (1 << (((val) >> 5) & 0x03)) -#define FAN_STATUS_FROM_REG(val) ((val) & 0x07) - -#define FAN_CONFIG_MONITOR(val, nr) (((val) >> (2 + (nr) * 3)) & 1) -#define FAN_CONFIG_CONTROL(val, nr) (((val) >> (3 + (nr) * 3)) & 1) -#define FAN_CONFIG_INVERT(val, nr) (((val) >> (4 + (nr) * 3)) & 1) - -#define PWM_FROM_REG(val, inv) ((inv) ? 255 - (val) : (val)) -static inline u8 PWM_TO_REG(int val, int inv) -{ - if (inv) - val = 255 - val; - if (val < 0) - return 0; - if (val > 255) - return 255; - return val; -} - -/* - * Voltage registers and conversions - */ - -#define PC87365_REG_IN_CONVRATE 0x07 -#define PC87365_REG_IN_CONFIG 0x08 -#define PC87365_REG_IN 0x0B -#define PC87365_REG_IN_MIN 0x0D -#define PC87365_REG_IN_MAX 0x0C -#define PC87365_REG_IN_STATUS 0x0A -#define PC87365_REG_IN_ALARMS1 0x00 -#define PC87365_REG_IN_ALARMS2 0x01 -#define PC87365_REG_VID 0x06 - -#define IN_FROM_REG(val, ref) (((val) * (ref) + 128) / 256) -#define IN_TO_REG(val, ref) ((val) < 0 ? 0 : \ - (val) * 256 >= (ref) * 255 ? 255 : \ - ((val) * 256 + (ref) / 2) / (ref)) - -/* - * Temperature registers and conversions - */ - -#define PC87365_REG_TEMP_CONFIG 0x08 -#define PC87365_REG_TEMP 0x0B -#define PC87365_REG_TEMP_MIN 0x0D -#define PC87365_REG_TEMP_MAX 0x0C -#define PC87365_REG_TEMP_CRIT 0x0E -#define PC87365_REG_TEMP_STATUS 0x0A -#define PC87365_REG_TEMP_ALARMS 0x00 - -#define TEMP_FROM_REG(val) ((val) * 1000) -#define TEMP_TO_REG(val) ((val) < -55000 ? -55 : \ - (val) > 127000 ? 127 : \ - (val) < 0 ? ((val) - 500) / 1000 : \ - ((val) + 500) / 1000) - -/* - * Device data - */ - -struct pc87360_data { - const char *name; - struct device *hwmon_dev; - struct mutex lock; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - int address[3]; - - u8 fannr, innr, tempnr; - - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - u8 fan_status[3]; /* Register value */ - u8 pwm[3]; /* Register value */ - u16 fan_conf; /* Configuration register values, combined */ - - u16 in_vref; /* 1 mV/bit */ - u8 in[14]; /* Register value */ - u8 in_min[14]; /* Register value */ - u8 in_max[14]; /* Register value */ - u8 in_crit[3]; /* Register value */ - u8 in_status[14]; /* Register value */ - u16 in_alarms; /* Register values, combined, masked */ - u8 vid_conf; /* Configuration register value */ - u8 vrm; - u8 vid; /* Register value */ - - s8 temp[3]; /* Register value */ - s8 temp_min[3]; /* Register value */ - s8 temp_max[3]; /* Register value */ - s8 temp_crit[3]; /* Register value */ - u8 temp_status[3]; /* Register value */ - u8 temp_alarms; /* Register value, masked */ -}; - -/* - * Functions declaration - */ - -static int pc87360_probe(struct platform_device *pdev); -static int __devexit pc87360_remove(struct platform_device *pdev); - -static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, - u8 reg); -static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, - u8 reg, u8 value); -static void pc87360_init_device(struct platform_device *pdev, - int use_thermistors); -static struct pc87360_data *pc87360_update_device(struct device *dev); - -/* - * Driver data - */ - -static struct platform_driver pc87360_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "pc87360", - }, - .probe = pc87360_probe, - .remove = __devexit_p(pc87360_remove), -}; - -/* - * Sysfs stuff - */ - -static ssize_t show_fan_input(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan[attr->index], - FAN_DIV_FROM_REG(data->fan_status[attr->index]))); -} -static ssize_t show_fan_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", FAN_FROM_REG(data->fan_min[attr->index], - FAN_DIV_FROM_REG(data->fan_status[attr->index]))); -} -static ssize_t show_fan_div(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", - FAN_DIV_FROM_REG(data->fan_status[attr->index])); -} -static ssize_t show_fan_status(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", - FAN_STATUS_FROM_REG(data->fan_status[attr->index])); -} -static ssize_t set_fan_min(struct device *dev, - struct device_attribute *devattr, const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long fan_min; - int err; - - err = kstrtol(buf, 10, &fan_min); - if (err) - return err; - - mutex_lock(&data->update_lock); - fan_min = FAN_TO_REG(fan_min, - FAN_DIV_FROM_REG(data->fan_status[attr->index])); - - /* If it wouldn't fit, change clock divisor */ - while (fan_min > 255 - && (data->fan_status[attr->index] & 0x60) != 0x60) { - fan_min >>= 1; - data->fan[attr->index] >>= 1; - data->fan_status[attr->index] += 0x20; - } - data->fan_min[attr->index] = fan_min > 255 ? 255 : fan_min; - pc87360_write_value(data, LD_FAN, NO_BANK, - PC87360_REG_FAN_MIN(attr->index), - data->fan_min[attr->index]); - - /* Write new divider, preserve alarm bits */ - pc87360_write_value(data, LD_FAN, NO_BANK, - PC87360_REG_FAN_STATUS(attr->index), - data->fan_status[attr->index] & 0xF9); - mutex_unlock(&data->update_lock); - - return count; -} - -static struct sensor_device_attribute fan_input[] = { - SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0), - SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1), - SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2), -}; -static struct sensor_device_attribute fan_status[] = { - SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0), - SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1), - SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2), -}; -static struct sensor_device_attribute 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), -}; -static struct sensor_device_attribute fan_min[] = { - SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0), - SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1), - SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2), -}; - -#define FAN_UNIT_ATTRS(X) \ -{ &fan_input[X].dev_attr.attr, \ - &fan_status[X].dev_attr.attr, \ - &fan_div[X].dev_attr.attr, \ - &fan_min[X].dev_attr.attr, \ - NULL \ -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", - PWM_FROM_REG(data->pwm[attr->index], - FAN_CONFIG_INVERT(data->fan_conf, - attr->index))); -} -static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm[attr->index] = PWM_TO_REG(val, - FAN_CONFIG_INVERT(data->fan_conf, attr->index)); - pc87360_write_value(data, LD_FAN, NO_BANK, PC87360_REG_PWM(attr->index), - data->pwm[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1), - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2), -}; - -static struct attribute *pc8736x_fan_attr[][5] = { - FAN_UNIT_ATTRS(0), - FAN_UNIT_ATTRS(1), - FAN_UNIT_ATTRS(2) -}; - -static const struct attribute_group pc8736x_fan_attr_group[] = { - { .attrs = pc8736x_fan_attr[0], }, - { .attrs = pc8736x_fan_attr[1], }, - { .attrs = pc8736x_fan_attr[2], }, -}; - -static ssize_t show_in_input(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], - data->in_vref)); -} -static ssize_t show_in_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], - data->in_vref)); -} -static ssize_t show_in_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], - data->in_vref)); -} -static ssize_t show_in_status(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", data->in_status[attr->index]); -} -static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MIN, - data->in_min[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[attr->index] = IN_TO_REG(val, - data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_IN_MAX, - data->in_max[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute in_input[] = { - SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7), - SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8), - SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9), - SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10), -}; -static struct sensor_device_attribute in_status[] = { - SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0), - SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1), - SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2), - SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3), - SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4), - SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5), - SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6), - SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7), - SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8), - SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9), - SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10), -}; -static struct sensor_device_attribute in_min[] = { - SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0), - SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1), - SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2), - SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3), - SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4), - SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5), - SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6), - SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7), - SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8), - SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9), - SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10), -}; -static struct sensor_device_attribute in_max[] = { - SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0), - SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1), - SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2), - SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3), - SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4), - SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5), - SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6), - SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7), - SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8), - SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9), - SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10), -}; - -/* (temp & vin) channel status register alarm bits (pdf sec.11.5.12) */ -#define CHAN_ALM_MIN 0x02 /* min limit crossed */ -#define CHAN_ALM_MAX 0x04 /* max limit exceeded */ -#define TEMP_ALM_CRIT 0x08 /* temp crit exceeded (temp only) */ - -/* - * show_in_min/max_alarm() reads data from the per-channel status - * register (sec 11.5.12), not the vin event status registers (sec - * 11.5.2) that (legacy) show_in_alarm() resds (via data->in_alarms) - */ - -static ssize_t show_in_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN)); -} -static ssize_t show_in_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX)); -} - -static struct sensor_device_attribute in_min_alarm[] = { - SENSOR_ATTR(in0_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 0), - SENSOR_ATTR(in1_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 1), - SENSOR_ATTR(in2_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 2), - SENSOR_ATTR(in3_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 3), - SENSOR_ATTR(in4_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 4), - SENSOR_ATTR(in5_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 5), - SENSOR_ATTR(in6_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 6), - SENSOR_ATTR(in7_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 7), - SENSOR_ATTR(in8_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 8), - SENSOR_ATTR(in9_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 9), - SENSOR_ATTR(in10_min_alarm, S_IRUGO, show_in_min_alarm, NULL, 10), -}; -static struct sensor_device_attribute in_max_alarm[] = { - SENSOR_ATTR(in0_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 0), - SENSOR_ATTR(in1_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 1), - SENSOR_ATTR(in2_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 2), - SENSOR_ATTR(in3_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 3), - SENSOR_ATTR(in4_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 4), - SENSOR_ATTR(in5_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 5), - SENSOR_ATTR(in6_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 6), - SENSOR_ATTR(in7_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 7), - SENSOR_ATTR(in8_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 8), - SENSOR_ATTR(in9_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 9), - SENSOR_ATTR(in10_max_alarm, S_IRUGO, show_in_max_alarm, NULL, 10), -}; - -#define VIN_UNIT_ATTRS(X) \ - &in_input[X].dev_attr.attr, \ - &in_status[X].dev_attr.attr, \ - &in_min[X].dev_attr.attr, \ - &in_max[X].dev_attr.attr, \ - &in_min_alarm[X].dev_attr.attr, \ - &in_max_alarm[X].dev_attr.attr - -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct pc87360_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%u\n", data->vrm); -} -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct pc87360_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); - -static ssize_t show_in_alarms(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", data->in_alarms); -} -static DEVICE_ATTR(alarms_in, S_IRUGO, show_in_alarms, NULL); - -static struct attribute *pc8736x_vin_attr_array[] = { - VIN_UNIT_ATTRS(0), - VIN_UNIT_ATTRS(1), - VIN_UNIT_ATTRS(2), - VIN_UNIT_ATTRS(3), - VIN_UNIT_ATTRS(4), - VIN_UNIT_ATTRS(5), - VIN_UNIT_ATTRS(6), - VIN_UNIT_ATTRS(7), - VIN_UNIT_ATTRS(8), - VIN_UNIT_ATTRS(9), - VIN_UNIT_ATTRS(10), - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - &dev_attr_alarms_in.attr, - NULL -}; -static const struct attribute_group pc8736x_vin_group = { - .attrs = pc8736x_vin_attr_array, -}; - -static ssize_t show_therm_input(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in[attr->index], - data->in_vref)); -} -static ssize_t show_therm_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_min[attr->index], - data->in_vref)); -} -static ssize_t show_therm_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_max[attr->index], - data->in_vref)); -} -static ssize_t show_therm_crit(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", IN_FROM_REG(data->in_crit[attr->index-11], - data->in_vref)); -} -static ssize_t show_therm_status(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", data->in_status[attr->index]); -} - -static ssize_t set_therm_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[attr->index] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MIN, - data->in_min[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_therm_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[attr->index] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_MAX, - data->in_max[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_therm_crit(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_crit[attr->index-11] = IN_TO_REG(val, data->in_vref); - pc87360_write_value(data, LD_IN, attr->index, PC87365_REG_TEMP_CRIT, - data->in_crit[attr->index-11]); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * the +11 term below reflects the fact that VLM units 11,12,13 are - * used in the chip to measure voltage across the thermistors - */ -static struct sensor_device_attribute therm_input[] = { - SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0 + 11), - SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1 + 11), - SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2 + 11), -}; -static struct sensor_device_attribute therm_status[] = { - SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0 + 11), - SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1 + 11), - SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2 + 11), -}; -static struct sensor_device_attribute therm_min[] = { - SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR, - show_therm_min, set_therm_min, 0 + 11), - SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR, - show_therm_min, set_therm_min, 1 + 11), - SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR, - show_therm_min, set_therm_min, 2 + 11), -}; -static struct sensor_device_attribute therm_max[] = { - SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, - show_therm_max, set_therm_max, 0 + 11), - SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, - show_therm_max, set_therm_max, 1 + 11), - SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, - show_therm_max, set_therm_max, 2 + 11), -}; -static struct sensor_device_attribute therm_crit[] = { - SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR, - show_therm_crit, set_therm_crit, 0 + 11), - SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR, - show_therm_crit, set_therm_crit, 1 + 11), - SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR, - show_therm_crit, set_therm_crit, 2 + 11), -}; - -/* - * show_therm_min/max_alarm() reads data from the per-channel voltage - * status register (sec 11.5.12) - */ - -static ssize_t show_therm_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MIN)); -} -static ssize_t show_therm_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->in_status[nr] & CHAN_ALM_MAX)); -} -static ssize_t show_therm_crit_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->in_status[nr] & TEMP_ALM_CRIT)); -} - -static struct sensor_device_attribute therm_min_alarm[] = { - SENSOR_ATTR(temp4_min_alarm, S_IRUGO, - show_therm_min_alarm, NULL, 0 + 11), - SENSOR_ATTR(temp5_min_alarm, S_IRUGO, - show_therm_min_alarm, NULL, 1 + 11), - SENSOR_ATTR(temp6_min_alarm, S_IRUGO, - show_therm_min_alarm, NULL, 2 + 11), -}; -static struct sensor_device_attribute therm_max_alarm[] = { - SENSOR_ATTR(temp4_max_alarm, S_IRUGO, - show_therm_max_alarm, NULL, 0 + 11), - SENSOR_ATTR(temp5_max_alarm, S_IRUGO, - show_therm_max_alarm, NULL, 1 + 11), - SENSOR_ATTR(temp6_max_alarm, S_IRUGO, - show_therm_max_alarm, NULL, 2 + 11), -}; -static struct sensor_device_attribute therm_crit_alarm[] = { - SENSOR_ATTR(temp4_crit_alarm, S_IRUGO, - show_therm_crit_alarm, NULL, 0 + 11), - SENSOR_ATTR(temp5_crit_alarm, S_IRUGO, - show_therm_crit_alarm, NULL, 1 + 11), - SENSOR_ATTR(temp6_crit_alarm, S_IRUGO, - show_therm_crit_alarm, NULL, 2 + 11), -}; - -#define THERM_UNIT_ATTRS(X) \ - &therm_input[X].dev_attr.attr, \ - &therm_status[X].dev_attr.attr, \ - &therm_min[X].dev_attr.attr, \ - &therm_max[X].dev_attr.attr, \ - &therm_crit[X].dev_attr.attr, \ - &therm_min_alarm[X].dev_attr.attr, \ - &therm_max_alarm[X].dev_attr.attr, \ - &therm_crit_alarm[X].dev_attr.attr - -static struct attribute *pc8736x_therm_attr_array[] = { - THERM_UNIT_ATTRS(0), - THERM_UNIT_ATTRS(1), - THERM_UNIT_ATTRS(2), - NULL -}; -static const struct attribute_group pc8736x_therm_group = { - .attrs = pc8736x_therm_attr_array, -}; - -static ssize_t show_temp_input(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); -} - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[attr->index])); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[attr->index])); -} - -static ssize_t show_temp_crit(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%d\n", - TEMP_FROM_REG(data->temp_crit[attr->index])); -} - -static ssize_t show_temp_status(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%d\n", data->temp_status[attr->index]); -} - -static ssize_t set_temp_min(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[attr->index] = TEMP_TO_REG(val); - pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MIN, - data->temp_min[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_max(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[attr->index] = TEMP_TO_REG(val); - pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_MAX, - data->temp_max[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_crit(struct device *dev, - struct device_attribute *devattr, const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct pc87360_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_crit[attr->index] = TEMP_TO_REG(val); - pc87360_write_value(data, LD_TEMP, attr->index, PC87365_REG_TEMP_CRIT, - data->temp_crit[attr->index]); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute temp_input[] = { - SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0), - SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1), - SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2), -}; -static struct sensor_device_attribute temp_status[] = { - SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0), - SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1), - SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2), -}; -static struct sensor_device_attribute temp_min[] = { - SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR, - show_temp_min, set_temp_min, 0), - SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR, - show_temp_min, set_temp_min, 1), - SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR, - show_temp_min, set_temp_min, 2), -}; -static struct sensor_device_attribute temp_max[] = { - SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 0), - SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 1), - SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, - show_temp_max, set_temp_max, 2), -}; -static struct sensor_device_attribute temp_crit[] = { - SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR, - show_temp_crit, set_temp_crit, 0), - SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR, - show_temp_crit, set_temp_crit, 1), - SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR, - show_temp_crit, set_temp_crit, 2), -}; - -static ssize_t show_temp_alarms(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - return sprintf(buf, "%u\n", data->temp_alarms); -} - -static DEVICE_ATTR(alarms_temp, S_IRUGO, show_temp_alarms, NULL); - -/* - * show_temp_min/max_alarm() reads data from the per-channel status - * register (sec 12.3.7), not the temp event status registers (sec - * 12.3.2) that show_temp_alarm() reads (via data->temp_alarms) - */ - -static ssize_t show_temp_min_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MIN)); -} - -static ssize_t show_temp_max_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->temp_status[nr] & CHAN_ALM_MAX)); -} - -static ssize_t show_temp_crit_alarm(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_ALM_CRIT)); -} - -static struct sensor_device_attribute temp_min_alarm[] = { - SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 0), - SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 1), - SENSOR_ATTR(temp3_min_alarm, S_IRUGO, show_temp_min_alarm, NULL, 2), -}; - -static struct sensor_device_attribute temp_max_alarm[] = { - SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 0), - SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 1), - SENSOR_ATTR(temp3_max_alarm, S_IRUGO, show_temp_max_alarm, NULL, 2), -}; - -static struct sensor_device_attribute temp_crit_alarm[] = { - SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 0), - SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 1), - SENSOR_ATTR(temp3_crit_alarm, S_IRUGO, show_temp_crit_alarm, NULL, 2), -}; - -#define TEMP_FAULT 0x40 /* open diode */ -static ssize_t show_temp_fault(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = pc87360_update_device(dev); - unsigned nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", !!(data->temp_status[nr] & TEMP_FAULT)); -} -static struct sensor_device_attribute temp_fault[] = { - SENSOR_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0), - SENSOR_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1), - SENSOR_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2), -}; - -#define TEMP_UNIT_ATTRS(X) \ -{ &temp_input[X].dev_attr.attr, \ - &temp_status[X].dev_attr.attr, \ - &temp_min[X].dev_attr.attr, \ - &temp_max[X].dev_attr.attr, \ - &temp_crit[X].dev_attr.attr, \ - &temp_min_alarm[X].dev_attr.attr, \ - &temp_max_alarm[X].dev_attr.attr, \ - &temp_crit_alarm[X].dev_attr.attr, \ - &temp_fault[X].dev_attr.attr, \ - NULL \ -} - -static struct attribute *pc8736x_temp_attr[][10] = { - TEMP_UNIT_ATTRS(0), - TEMP_UNIT_ATTRS(1), - TEMP_UNIT_ATTRS(2) -}; - -static const struct attribute_group pc8736x_temp_attr_group[] = { - { .attrs = pc8736x_temp_attr[0] }, - { .attrs = pc8736x_temp_attr[1] }, - { .attrs = pc8736x_temp_attr[2] } -}; - -static ssize_t show_name(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct pc87360_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -/* - * Device detection, registration and update - */ - -static int __init pc87360_find(int sioaddr, u8 *devid, - unsigned short *addresses) -{ - u16 val; - int i; - int nrdev; /* logical device count */ - - /* No superio_enter */ - - /* Identify device */ - val = force_id ? force_id : superio_inb(sioaddr, DEVID); - switch (val) { - case 0xE1: /* PC87360 */ - case 0xE8: /* PC87363 */ - case 0xE4: /* PC87364 */ - nrdev = 1; - break; - case 0xE5: /* PC87365 */ - case 0xE9: /* PC87366 */ - nrdev = 3; - break; - default: - superio_exit(sioaddr); - return -ENODEV; - } - /* Remember the device id */ - *devid = val; - - for (i = 0; i < nrdev; i++) { - /* select logical device */ - superio_outb(sioaddr, DEV, logdev[i]); - - val = superio_inb(sioaddr, ACT); - if (!(val & 0x01)) { - pr_info("Device 0x%02x not activated\n", logdev[i]); - continue; - } - - val = (superio_inb(sioaddr, BASE) << 8) - | superio_inb(sioaddr, BASE + 1); - if (!val) { - pr_info("Base address not set for device 0x%02x\n", - logdev[i]); - continue; - } - - addresses[i] = val; - - if (i == 0) { /* Fans */ - confreg[0] = superio_inb(sioaddr, 0xF0); - confreg[1] = superio_inb(sioaddr, 0xF1); - - pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 1, - (confreg[0] >> 2) & 1, (confreg[0] >> 3) & 1, - (confreg[0] >> 4) & 1); - pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 2, - (confreg[0] >> 5) & 1, (confreg[0] >> 6) & 1, - (confreg[0] >> 7) & 1); - pr_debug("Fan %d: mon=%d ctrl=%d inv=%d\n", 3, - confreg[1] & 1, (confreg[1] >> 1) & 1, - (confreg[1] >> 2) & 1); - } else if (i == 1) { /* Voltages */ - /* Are we using thermistors? */ - if (*devid == 0xE9) { /* PC87366 */ - /* - * These registers are not logical-device - * specific, just that we won't need them if - * we don't use the VLM device - */ - confreg[2] = superio_inb(sioaddr, 0x2B); - confreg[3] = superio_inb(sioaddr, 0x25); - - if (confreg[2] & 0x40) { - pr_info("Using thermistors for " - "temperature monitoring\n"); - } - if (confreg[3] & 0xE0) { - pr_info("VID inputs routed (mode %u)\n", - confreg[3] >> 5); - } - } - } - } - - superio_exit(sioaddr); - return 0; -} - -static void pc87360_remove_files(struct device *dev) -{ - int i; - - device_remove_file(dev, &dev_attr_name); - device_remove_file(dev, &dev_attr_alarms_temp); - for (i = 0; i < ARRAY_SIZE(pc8736x_temp_attr_group); i++) - sysfs_remove_group(&dev->kobj, &pc8736x_temp_attr_group[i]); - for (i = 0; i < ARRAY_SIZE(pc8736x_fan_attr_group); i++) { - sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_attr_group[i]); - device_remove_file(dev, &pwm[i].dev_attr); - } - sysfs_remove_group(&dev->kobj, &pc8736x_therm_group); - sysfs_remove_group(&dev->kobj, &pc8736x_vin_group); -} - -static int __devinit pc87360_probe(struct platform_device *pdev) -{ - int i; - struct pc87360_data *data; - int err = 0; - const char *name = "pc87360"; - int use_thermistors = 0; - struct device *dev = &pdev->dev; - - data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->fannr = 2; - data->innr = 0; - data->tempnr = 0; - - switch (devid) { - case 0xe8: - name = "pc87363"; - break; - case 0xe4: - name = "pc87364"; - data->fannr = 3; - break; - case 0xe5: - name = "pc87365"; - data->fannr = extra_isa[0] ? 3 : 0; - data->innr = extra_isa[1] ? 11 : 0; - data->tempnr = extra_isa[2] ? 2 : 0; - break; - case 0xe9: - name = "pc87366"; - data->fannr = extra_isa[0] ? 3 : 0; - data->innr = extra_isa[1] ? 14 : 0; - data->tempnr = extra_isa[2] ? 3 : 0; - break; - } - - data->name = name; - data->valid = 0; - mutex_init(&data->lock); - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - for (i = 0; i < LDNI_MAX; i++) { - data->address[i] = extra_isa[i]; - if (data->address[i] - && !request_region(extra_isa[i], PC87360_EXTENT, - pc87360_driver.driver.name)) { - dev_err(dev, "Region 0x%x-0x%x already " - "in use!\n", extra_isa[i], - extra_isa[i]+PC87360_EXTENT-1); - for (i--; i >= 0; i--) - release_region(extra_isa[i], PC87360_EXTENT); - err = -EBUSY; - goto ERROR1; - } - } - - /* Retrieve the fans configuration from Super-I/O space */ - if (data->fannr) - data->fan_conf = confreg[0] | (confreg[1] << 8); - - /* - * Use the correct reference voltage - * Unless both the VLM and the TMS logical devices agree to - * use an external Vref, the internal one is used. - */ - if (data->innr) { - i = pc87360_read_value(data, LD_IN, NO_BANK, - PC87365_REG_IN_CONFIG); - if (data->tempnr) { - i &= pc87360_read_value(data, LD_TEMP, NO_BANK, - PC87365_REG_TEMP_CONFIG); - } - data->in_vref = (i&0x02) ? 3025 : 2966; - dev_dbg(dev, "Using %s reference voltage\n", - (i&0x02) ? "external" : "internal"); - - data->vid_conf = confreg[3]; - data->vrm = vid_which_vrm(); - } - - /* Fan clock dividers may be needed before any data is read */ - for (i = 0; i < data->fannr; i++) { - if (FAN_CONFIG_MONITOR(data->fan_conf, i)) - data->fan_status[i] = pc87360_read_value(data, - LD_FAN, NO_BANK, - PC87360_REG_FAN_STATUS(i)); - } - - if (init > 0) { - if (devid == 0xe9 && data->address[1]) /* PC87366 */ - use_thermistors = confreg[2] & 0x40; - - pc87360_init_device(pdev, use_thermistors); - } - - /* Register all-or-nothing sysfs groups */ - - if (data->innr) { - err = sysfs_create_group(&dev->kobj, &pc8736x_vin_group); - if (err) - goto ERROR3; - } - - if (data->innr == 14) { - err = sysfs_create_group(&dev->kobj, &pc8736x_therm_group); - if (err) - goto ERROR3; - } - - /* create device attr-files for varying sysfs groups */ - - if (data->tempnr) { - for (i = 0; i < data->tempnr; i++) { - err = sysfs_create_group(&dev->kobj, - &pc8736x_temp_attr_group[i]); - if (err) - goto ERROR3; - } - err = device_create_file(dev, &dev_attr_alarms_temp); - if (err) - goto ERROR3; - } - - for (i = 0; i < data->fannr; i++) { - if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { - err = sysfs_create_group(&dev->kobj, - &pc8736x_fan_attr_group[i]); - if (err) - goto ERROR3; - } - if (FAN_CONFIG_CONTROL(data->fan_conf, i)) { - err = device_create_file(dev, &pwm[i].dev_attr); - if (err) - goto ERROR3; - } - } - - err = device_create_file(dev, &dev_attr_name); - if (err) - goto ERROR3; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto ERROR3; - } - return 0; - -ERROR3: - pc87360_remove_files(dev); - for (i = 0; i < 3; i++) { - if (data->address[i]) - release_region(data->address[i], PC87360_EXTENT); - } -ERROR1: - kfree(data); - return err; -} - -static int __devexit pc87360_remove(struct platform_device *pdev) -{ - struct pc87360_data *data = platform_get_drvdata(pdev); - int i; - - hwmon_device_unregister(data->hwmon_dev); - pc87360_remove_files(&pdev->dev); - for (i = 0; i < 3; i++) { - if (data->address[i]) - release_region(data->address[i], PC87360_EXTENT); - } - kfree(data); - - return 0; -} - -/* - * ldi is the logical device index - * bank is for voltages and temperatures only - */ -static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank, - u8 reg) -{ - int res; - - mutex_lock(&(data->lock)); - if (bank != NO_BANK) - outb_p(bank, data->address[ldi] + PC87365_REG_BANK); - res = inb_p(data->address[ldi] + reg); - mutex_unlock(&(data->lock)); - - return res; -} - -static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank, - u8 reg, u8 value) -{ - mutex_lock(&(data->lock)); - if (bank != NO_BANK) - outb_p(bank, data->address[ldi] + PC87365_REG_BANK); - outb_p(value, data->address[ldi] + reg); - mutex_unlock(&(data->lock)); -} - -/* (temp & vin) channel conversion status register flags (pdf sec.11.5.12) */ -#define CHAN_CNVRTD 0x80 /* new data ready */ -#define CHAN_ENA 0x01 /* enabled channel (temp or vin) */ -#define CHAN_ALM_ENA 0x10 /* propagate to alarms-reg ?? (chk val!) */ -#define CHAN_READY (CHAN_ENA|CHAN_CNVRTD) /* sample ready mask */ - -#define TEMP_OTS_OE 0x20 /* OTS Output Enable */ -#define VIN_RW1C_MASK (CHAN_READY|CHAN_ALM_MAX|CHAN_ALM_MIN) /* 0x87 */ -#define TEMP_RW1C_MASK (VIN_RW1C_MASK|TEMP_ALM_CRIT|TEMP_FAULT) /* 0xCF */ - -static void pc87360_init_device(struct platform_device *pdev, - int use_thermistors) -{ - struct pc87360_data *data = platform_get_drvdata(pdev); - int i, nr; - const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 }; - const u8 init_temp[3] = { 2, 2, 1 }; - u8 reg; - - if (init >= 2 && data->innr) { - reg = pc87360_read_value(data, LD_IN, NO_BANK, - PC87365_REG_IN_CONVRATE); - dev_info(&pdev->dev, "VLM conversion set to " - "1s period, 160us delay\n"); - pc87360_write_value(data, LD_IN, NO_BANK, - PC87365_REG_IN_CONVRATE, - (reg & 0xC0) | 0x11); - } - - nr = data->innr < 11 ? data->innr : 11; - for (i = 0; i < nr; i++) { - reg = pc87360_read_value(data, LD_IN, i, - PC87365_REG_IN_STATUS); - dev_dbg(&pdev->dev, "bios in%d status:0x%02x\n", i, reg); - if (init >= init_in[i]) { - /* Forcibly enable voltage channel */ - if (!(reg & CHAN_ENA)) { - dev_dbg(&pdev->dev, "Forcibly " - "enabling in%d\n", i); - pc87360_write_value(data, LD_IN, i, - PC87365_REG_IN_STATUS, - (reg & 0x68) | 0x87); - } - } - } - - /* - * We can't blindly trust the Super-I/O space configuration bit, - * most BIOS won't set it properly - */ - dev_dbg(&pdev->dev, "bios thermistors:%d\n", use_thermistors); - for (i = 11; i < data->innr; i++) { - reg = pc87360_read_value(data, LD_IN, i, - PC87365_REG_TEMP_STATUS); - use_thermistors = use_thermistors || (reg & CHAN_ENA); - /* thermistors are temp[4-6], measured on vin[11-14] */ - dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i-7, reg); - } - dev_dbg(&pdev->dev, "using thermistors:%d\n", use_thermistors); - - i = use_thermistors ? 2 : 0; - for (; i < data->tempnr; i++) { - reg = pc87360_read_value(data, LD_TEMP, i, - PC87365_REG_TEMP_STATUS); - dev_dbg(&pdev->dev, "bios temp%d_status:0x%02x\n", i + 1, reg); - if (init >= init_temp[i]) { - /* Forcibly enable temperature channel */ - if (!(reg & CHAN_ENA)) { - dev_dbg(&pdev->dev, - "Forcibly enabling temp%d\n", i + 1); - pc87360_write_value(data, LD_TEMP, i, - PC87365_REG_TEMP_STATUS, - 0xCF); - } - } - } - - if (use_thermistors) { - for (i = 11; i < data->innr; i++) { - if (init >= init_in[i]) { - /* - * The pin may already be used by thermal - * diodes - */ - reg = pc87360_read_value(data, LD_TEMP, - (i - 11) / 2, PC87365_REG_TEMP_STATUS); - if (reg & CHAN_ENA) { - dev_dbg(&pdev->dev, - "Skipping temp%d, pin already in use by temp%d\n", - i - 7, (i - 11) / 2); - continue; - } - - /* Forcibly enable thermistor channel */ - reg = pc87360_read_value(data, LD_IN, i, - PC87365_REG_IN_STATUS); - if (!(reg & CHAN_ENA)) { - dev_dbg(&pdev->dev, - "Forcibly enabling temp%d\n", - i - 7); - pc87360_write_value(data, LD_IN, i, - PC87365_REG_TEMP_STATUS, - (reg & 0x60) | 0x8F); - } - } - } - } - - if (data->innr) { - reg = pc87360_read_value(data, LD_IN, NO_BANK, - PC87365_REG_IN_CONFIG); - dev_dbg(&pdev->dev, "bios vin-cfg:0x%02x\n", reg); - if (reg & CHAN_ENA) { - dev_dbg(&pdev->dev, - "Forcibly enabling monitoring (VLM)\n"); - pc87360_write_value(data, LD_IN, NO_BANK, - PC87365_REG_IN_CONFIG, - reg & 0xFE); - } - } - - if (data->tempnr) { - reg = pc87360_read_value(data, LD_TEMP, NO_BANK, - PC87365_REG_TEMP_CONFIG); - dev_dbg(&pdev->dev, "bios temp-cfg:0x%02x\n", reg); - if (reg & CHAN_ENA) { - dev_dbg(&pdev->dev, - "Forcibly enabling monitoring (TMS)\n"); - pc87360_write_value(data, LD_TEMP, NO_BANK, - PC87365_REG_TEMP_CONFIG, - reg & 0xFE); - } - - if (init >= 2) { - /* Chip config as documented by National Semi. */ - pc87360_write_value(data, LD_TEMP, 0xF, 0xA, 0x08); - /* - * We voluntarily omit the bank here, in case the - * sequence itself matters. It shouldn't be a problem, - * since nobody else is supposed to access the - * device at that point. - */ - pc87360_write_value(data, LD_TEMP, NO_BANK, 0xB, 0x04); - pc87360_write_value(data, LD_TEMP, NO_BANK, 0xC, 0x35); - pc87360_write_value(data, LD_TEMP, NO_BANK, 0xD, 0x05); - pc87360_write_value(data, LD_TEMP, NO_BANK, 0xE, 0x05); - } - } -} - -static void pc87360_autodiv(struct device *dev, int nr) -{ - struct pc87360_data *data = dev_get_drvdata(dev); - u8 old_min = data->fan_min[nr]; - - /* Increase clock divider if needed and possible */ - if ((data->fan_status[nr] & 0x04) /* overflow flag */ - || (data->fan[nr] >= 224)) { /* next to overflow */ - if ((data->fan_status[nr] & 0x60) != 0x60) { - data->fan_status[nr] += 0x20; - data->fan_min[nr] >>= 1; - data->fan[nr] >>= 1; - dev_dbg(dev, "Increasing " - "clock divider to %d for fan %d\n", - FAN_DIV_FROM_REG(data->fan_status[nr]), nr + 1); - } - } else { - /* Decrease clock divider if possible */ - while (!(data->fan_min[nr] & 0x80) /* min "nails" divider */ - && data->fan[nr] < 85 /* bad accuracy */ - && (data->fan_status[nr] & 0x60) != 0x00) { - data->fan_status[nr] -= 0x20; - data->fan_min[nr] <<= 1; - data->fan[nr] <<= 1; - dev_dbg(dev, "Decreasing " - "clock divider to %d for fan %d\n", - FAN_DIV_FROM_REG(data->fan_status[nr]), - nr + 1); - } - } - - /* Write new fan min if it changed */ - if (old_min != data->fan_min[nr]) { - pc87360_write_value(data, LD_FAN, NO_BANK, - PC87360_REG_FAN_MIN(nr), - data->fan_min[nr]); - } -} - -static struct pc87360_data *pc87360_update_device(struct device *dev) -{ - struct pc87360_data *data = dev_get_drvdata(dev); - u8 i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - dev_dbg(dev, "Data update\n"); - - /* Fans */ - for (i = 0; i < data->fannr; i++) { - if (FAN_CONFIG_MONITOR(data->fan_conf, i)) { - data->fan_status[i] = - pc87360_read_value(data, LD_FAN, - NO_BANK, PC87360_REG_FAN_STATUS(i)); - data->fan[i] = pc87360_read_value(data, LD_FAN, - NO_BANK, PC87360_REG_FAN(i)); - data->fan_min[i] = pc87360_read_value(data, - LD_FAN, NO_BANK, - PC87360_REG_FAN_MIN(i)); - /* Change clock divider if needed */ - pc87360_autodiv(dev, i); - /* Clear bits and write new divider */ - pc87360_write_value(data, LD_FAN, NO_BANK, - PC87360_REG_FAN_STATUS(i), - data->fan_status[i]); - } - if (FAN_CONFIG_CONTROL(data->fan_conf, i)) - data->pwm[i] = pc87360_read_value(data, LD_FAN, - NO_BANK, PC87360_REG_PWM(i)); - } - - /* Voltages */ - for (i = 0; i < data->innr; i++) { - data->in_status[i] = pc87360_read_value(data, LD_IN, i, - PC87365_REG_IN_STATUS); - /* Clear bits */ - pc87360_write_value(data, LD_IN, i, - PC87365_REG_IN_STATUS, - data->in_status[i]); - if ((data->in_status[i] & CHAN_READY) == CHAN_READY) { - data->in[i] = pc87360_read_value(data, LD_IN, - i, PC87365_REG_IN); - } - if (data->in_status[i] & CHAN_ENA) { - data->in_min[i] = pc87360_read_value(data, - LD_IN, i, - PC87365_REG_IN_MIN); - data->in_max[i] = pc87360_read_value(data, - LD_IN, i, - PC87365_REG_IN_MAX); - if (i >= 11) - data->in_crit[i-11] = - pc87360_read_value(data, LD_IN, - i, PC87365_REG_TEMP_CRIT); - } - } - if (data->innr) { - data->in_alarms = pc87360_read_value(data, LD_IN, - NO_BANK, PC87365_REG_IN_ALARMS1) - | ((pc87360_read_value(data, LD_IN, - NO_BANK, PC87365_REG_IN_ALARMS2) - & 0x07) << 8); - data->vid = (data->vid_conf & 0xE0) ? - pc87360_read_value(data, LD_IN, - NO_BANK, PC87365_REG_VID) : 0x1F; - } - - /* Temperatures */ - for (i = 0; i < data->tempnr; i++) { - data->temp_status[i] = pc87360_read_value(data, - LD_TEMP, i, - PC87365_REG_TEMP_STATUS); - /* Clear bits */ - pc87360_write_value(data, LD_TEMP, i, - PC87365_REG_TEMP_STATUS, - data->temp_status[i]); - if ((data->temp_status[i] & CHAN_READY) == CHAN_READY) { - data->temp[i] = pc87360_read_value(data, - LD_TEMP, i, - PC87365_REG_TEMP); - } - if (data->temp_status[i] & CHAN_ENA) { - data->temp_min[i] = pc87360_read_value(data, - LD_TEMP, i, - PC87365_REG_TEMP_MIN); - data->temp_max[i] = pc87360_read_value(data, - LD_TEMP, i, - PC87365_REG_TEMP_MAX); - data->temp_crit[i] = pc87360_read_value(data, - LD_TEMP, i, - PC87365_REG_TEMP_CRIT); - } - } - if (data->tempnr) { - data->temp_alarms = pc87360_read_value(data, LD_TEMP, - NO_BANK, PC87365_REG_TEMP_ALARMS) - & 0x3F; - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static int __init pc87360_device_add(unsigned short address) -{ - struct resource res[3]; - int err, i, res_count; - - pdev = platform_device_alloc("pc87360", address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - memset(res, 0, 3 * sizeof(struct resource)); - res_count = 0; - for (i = 0; i < 3; i++) { - if (!extra_isa[i]) - continue; - res[res_count].start = extra_isa[i]; - res[res_count].end = extra_isa[i] + PC87360_EXTENT - 1; - res[res_count].name = "pc87360", - res[res_count].flags = IORESOURCE_IO, - - err = acpi_check_resource_conflict(&res[res_count]); - if (err) - goto exit_device_put; - - res_count++; - } - - err = platform_device_add_resources(pdev, res, res_count); - if (err) { - pr_err("Device resources addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init pc87360_init(void) -{ - int err, i; - unsigned short address = 0; - - if (pc87360_find(0x2e, &devid, extra_isa) - && pc87360_find(0x4e, &devid, extra_isa)) { - pr_warn("PC8736x not detected, module not inserted\n"); - return -ENODEV; - } - - /* Arbitrarily pick one of the addresses */ - for (i = 0; i < 3; i++) { - if (extra_isa[i] != 0x0000) { - address = extra_isa[i]; - break; - } - } - - if (address == 0x0000) { - pr_warn("No active logical device, module not inserted\n"); - return -ENODEV; - } - - err = platform_driver_register(&pc87360_driver); - if (err) - goto exit; - - /* Sets global pdev as a side effect */ - err = pc87360_device_add(address); - if (err) - goto exit_driver; - - return 0; - - exit_driver: - platform_driver_unregister(&pc87360_driver); - exit: - return err; -} - -static void __exit pc87360_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&pc87360_driver); -} - - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("PC8736x hardware monitor"); -MODULE_LICENSE("GPL"); - -module_init(pc87360_init); -module_exit(pc87360_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/pc87427.c b/ANDROID_3.4.5/drivers/hwmon/pc87427.c deleted file mode 100644 index 37059a37..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pc87427.c +++ /dev/null @@ -1,1383 +0,0 @@ -/* - * pc87427.c - hardware monitoring driver for the - * National Semiconductor PC87427 Super-I/O chip - * Copyright (C) 2006, 2008, 2010 Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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. - * - * Supports the following chips: - * - * Chip #vin #fan #pwm #temp devid - * PC87427 - 8 4 6 0xF2 - * - * This driver assumes that no more than one chip is present. - * Only fans are fully supported so far. Temperatures are in read-only - * mode, and voltages aren't supported at all. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static struct platform_device *pdev; - -#define DRVNAME "pc87427" - -/* - * The lock mutex protects both the I/O accesses (needed because the - * device is using banked registers) and the register cache (needed to keep - * the data in the registers and the cache in sync at any time). - */ -struct pc87427_data { - struct device *hwmon_dev; - struct mutex lock; - int address[2]; - const char *name; - - unsigned long last_updated; /* in jiffies */ - u8 fan_enabled; /* bit vector */ - u16 fan[8]; /* register values */ - u16 fan_min[8]; /* register values */ - u8 fan_status[8]; /* register values */ - - u8 pwm_enabled; /* bit vector */ - u8 pwm_auto_ok; /* bit vector */ - u8 pwm_enable[4]; /* register values */ - u8 pwm[4]; /* register values */ - - u8 temp_enabled; /* bit vector */ - s16 temp[6]; /* register values */ - s8 temp_min[6]; /* register values */ - s8 temp_max[6]; /* register values */ - s8 temp_crit[6]; /* register values */ - u8 temp_status[6]; /* register values */ - u8 temp_type[6]; /* register values */ -}; - -struct pc87427_sio_data { - unsigned short address[2]; - u8 has_fanin; - u8 has_fanout; -}; - -/* - * Super-I/O registers and operations - */ - -#define SIOREG_LDSEL 0x07 /* Logical device select */ -#define SIOREG_DEVID 0x20 /* Device ID */ -#define SIOREG_CF2 0x22 /* Configuration 2 */ -#define SIOREG_CF3 0x23 /* Configuration 3 */ -#define SIOREG_CF4 0x24 /* Configuration 4 */ -#define SIOREG_CF5 0x25 /* Configuration 5 */ -#define SIOREG_CFB 0x2B /* Configuration B */ -#define SIOREG_CFC 0x2C /* Configuration C */ -#define SIOREG_CFD 0x2D /* Configuration D */ -#define SIOREG_ACT 0x30 /* Device activation */ -#define SIOREG_MAP 0x50 /* I/O or memory mapping */ -#define SIOREG_IOBASE 0x60 /* I/O base address */ - -static const u8 logdev[2] = { 0x09, 0x14 }; -static const char *logdev_str[2] = { DRVNAME " FMC", DRVNAME " HMC" }; -#define LD_FAN 0 -#define LD_IN 1 -#define LD_TEMP 1 - -static inline void superio_outb(int sioaddr, int reg, int val) -{ - outb(reg, sioaddr); - outb(val, sioaddr + 1); -} - -static inline int superio_inb(int sioaddr, int reg) -{ - outb(reg, sioaddr); - return inb(sioaddr + 1); -} - -static inline void superio_exit(int sioaddr) -{ - outb(0x02, sioaddr); - outb(0x02, sioaddr + 1); -} - -/* - * Logical devices - */ - -#define REGION_LENGTH 32 -#define PC87427_REG_BANK 0x0f -#define BANK_FM(nr) (nr) -#define BANK_FT(nr) (0x08 + (nr)) -#define BANK_FC(nr) (0x10 + (nr) * 2) -#define BANK_TM(nr) (nr) -#define BANK_VM(nr) (0x08 + (nr)) - -/* - * I/O access functions - */ - -/* ldi is the logical device index */ -static inline int pc87427_read8(struct pc87427_data *data, u8 ldi, u8 reg) -{ - return inb(data->address[ldi] + reg); -} - -/* Must be called with data->lock held, except during init */ -static inline int pc87427_read8_bank(struct pc87427_data *data, u8 ldi, - u8 bank, u8 reg) -{ - outb(bank, data->address[ldi] + PC87427_REG_BANK); - return inb(data->address[ldi] + reg); -} - -/* Must be called with data->lock held, except during init */ -static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi, - u8 bank, u8 reg, u8 value) -{ - outb(bank, data->address[ldi] + PC87427_REG_BANK); - outb(value, data->address[ldi] + reg); -} - -/* - * Fan registers and conversions - */ - -/* fan data registers are 16-bit wide */ -#define PC87427_REG_FAN 0x12 -#define PC87427_REG_FAN_MIN 0x14 -#define PC87427_REG_FAN_STATUS 0x10 - -#define FAN_STATUS_STALL (1 << 3) -#define FAN_STATUS_LOSPD (1 << 1) -#define FAN_STATUS_MONEN (1 << 0) - -/* - * Dedicated function to read all registers related to a given fan input. - * This saves us quite a few locks and bank selections. - * Must be called with data->lock held. - * nr is from 0 to 7 - */ -static void pc87427_readall_fan(struct pc87427_data *data, u8 nr) -{ - int iobase = data->address[LD_FAN]; - - outb(BANK_FM(nr), iobase + PC87427_REG_BANK); - data->fan[nr] = inw(iobase + PC87427_REG_FAN); - data->fan_min[nr] = inw(iobase + PC87427_REG_FAN_MIN); - data->fan_status[nr] = inb(iobase + PC87427_REG_FAN_STATUS); - /* Clear fan alarm bits */ - outb(data->fan_status[nr], iobase + PC87427_REG_FAN_STATUS); -} - -/* - * The 2 LSB of fan speed registers are used for something different. - * The actual 2 LSB of the measurements are not available. - */ -static inline unsigned long fan_from_reg(u16 reg) -{ - reg &= 0xfffc; - if (reg == 0x0000 || reg == 0xfffc) - return 0; - return 5400000UL / reg; -} - -/* The 2 LSB of the fan speed limit registers are not significant. */ -static inline u16 fan_to_reg(unsigned long val) -{ - if (val < 83UL) - return 0xffff; - if (val >= 1350000UL) - return 0x0004; - return ((1350000UL + val / 2) / val) << 2; -} - -/* - * PWM registers and conversions - */ - -#define PC87427_REG_PWM_ENABLE 0x10 -#define PC87427_REG_PWM_DUTY 0x12 - -#define PWM_ENABLE_MODE_MASK (7 << 4) -#define PWM_ENABLE_CTLEN (1 << 0) - -#define PWM_MODE_MANUAL (0 << 4) -#define PWM_MODE_AUTO (1 << 4) -#define PWM_MODE_OFF (2 << 4) -#define PWM_MODE_ON (7 << 4) - -/* - * Dedicated function to read all registers related to a given PWM output. - * This saves us quite a few locks and bank selections. - * Must be called with data->lock held. - * nr is from 0 to 3 - */ -static void pc87427_readall_pwm(struct pc87427_data *data, u8 nr) -{ - int iobase = data->address[LD_FAN]; - - outb(BANK_FC(nr), iobase + PC87427_REG_BANK); - data->pwm_enable[nr] = inb(iobase + PC87427_REG_PWM_ENABLE); - data->pwm[nr] = inb(iobase + PC87427_REG_PWM_DUTY); -} - -static inline int pwm_enable_from_reg(u8 reg) -{ - switch (reg & PWM_ENABLE_MODE_MASK) { - case PWM_MODE_ON: - return 0; - case PWM_MODE_MANUAL: - case PWM_MODE_OFF: - return 1; - case PWM_MODE_AUTO: - return 2; - default: - return -EPROTO; - } -} - -static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval) -{ - switch (val) { - default: - return PWM_MODE_ON; - case 1: - return pwmval ? PWM_MODE_MANUAL : PWM_MODE_OFF; - case 2: - return PWM_MODE_AUTO; - } -} - -/* - * Temperature registers and conversions - */ - -#define PC87427_REG_TEMP_STATUS 0x10 -#define PC87427_REG_TEMP 0x14 -#define PC87427_REG_TEMP_MAX 0x18 -#define PC87427_REG_TEMP_MIN 0x19 -#define PC87427_REG_TEMP_CRIT 0x1a -#define PC87427_REG_TEMP_TYPE 0x1d - -#define TEMP_STATUS_CHANEN (1 << 0) -#define TEMP_STATUS_LOWFLG (1 << 1) -#define TEMP_STATUS_HIGHFLG (1 << 2) -#define TEMP_STATUS_CRITFLG (1 << 3) -#define TEMP_STATUS_SENSERR (1 << 5) -#define TEMP_TYPE_MASK (3 << 5) - -#define TEMP_TYPE_THERMISTOR (1 << 5) -#define TEMP_TYPE_REMOTE_DIODE (2 << 5) -#define TEMP_TYPE_LOCAL_DIODE (3 << 5) - -/* - * Dedicated function to read all registers related to a given temperature - * input. This saves us quite a few locks and bank selections. - * Must be called with data->lock held. - * nr is from 0 to 5 - */ -static void pc87427_readall_temp(struct pc87427_data *data, u8 nr) -{ - int iobase = data->address[LD_TEMP]; - - outb(BANK_TM(nr), iobase + PC87427_REG_BANK); - data->temp[nr] = le16_to_cpu(inw(iobase + PC87427_REG_TEMP)); - data->temp_max[nr] = inb(iobase + PC87427_REG_TEMP_MAX); - data->temp_min[nr] = inb(iobase + PC87427_REG_TEMP_MIN); - data->temp_crit[nr] = inb(iobase + PC87427_REG_TEMP_CRIT); - data->temp_type[nr] = inb(iobase + PC87427_REG_TEMP_TYPE); - data->temp_status[nr] = inb(iobase + PC87427_REG_TEMP_STATUS); - /* Clear fan alarm bits */ - outb(data->temp_status[nr], iobase + PC87427_REG_TEMP_STATUS); -} - -static inline unsigned int temp_type_from_reg(u8 reg) -{ - switch (reg & TEMP_TYPE_MASK) { - case TEMP_TYPE_THERMISTOR: - return 4; - case TEMP_TYPE_REMOTE_DIODE: - case TEMP_TYPE_LOCAL_DIODE: - return 3; - default: - return 0; - } -} - -/* - * We assume 8-bit thermal sensors; 9-bit thermal sensors are possible - * too, but I have no idea how to figure out when they are used. - */ -static inline long temp_from_reg(s16 reg) -{ - return reg * 1000 / 256; -} - -static inline long temp_from_reg8(s8 reg) -{ - return reg * 1000; -} - -/* - * Data interface - */ - -static struct pc87427_data *pc87427_update_device(struct device *dev) -{ - struct pc87427_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->lock); - if (!time_after(jiffies, data->last_updated + HZ) - && data->last_updated) - goto done; - - /* Fans */ - for (i = 0; i < 8; i++) { - if (!(data->fan_enabled & (1 << i))) - continue; - pc87427_readall_fan(data, i); - } - - /* PWM outputs */ - for (i = 0; i < 4; i++) { - if (!(data->pwm_enabled & (1 << i))) - continue; - pc87427_readall_pwm(data, i); - } - - /* Temperature channels */ - for (i = 0; i < 6; i++) { - if (!(data->temp_enabled & (1 << i))) - continue; - pc87427_readall_temp(data, i); - } - - data->last_updated = jiffies; - -done: - mutex_unlock(&data->lock); - return data; -} - -static ssize_t show_fan_input(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%lu\n", fan_from_reg(data->fan[nr])); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%lu\n", fan_from_reg(data->fan_min[nr])); -} - -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", !!(data->fan_status[nr] - & FAN_STATUS_LOSPD)); -} - -static ssize_t show_fan_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", !!(data->fan_status[nr] - & FAN_STATUS_STALL)); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct pc87427_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; - unsigned long val; - int iobase = data->address[LD_FAN]; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->lock); - outb(BANK_FM(nr), iobase + PC87427_REG_BANK); - /* - * The low speed limit registers are read-only while monitoring - * is enabled, so we have to disable monitoring, then change the - * limit, and finally enable monitoring again. - */ - outb(0, iobase + PC87427_REG_FAN_STATUS); - data->fan_min[nr] = fan_to_reg(val); - outw(data->fan_min[nr], iobase + PC87427_REG_FAN_MIN); - outb(FAN_STATUS_MONEN, iobase + PC87427_REG_FAN_STATUS); - mutex_unlock(&data->lock); - - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan_input, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan_input, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan_input, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_input, S_IRUGO, show_fan_input, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 3); -static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 4); -static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 5); -static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 6); -static SENSOR_DEVICE_ATTR(fan8_min, S_IWUSR | S_IRUGO, - show_fan_min, set_fan_min, 7); - -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_fan_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_fan_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_fan_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_fan_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_fan_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_fan_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_alarm, S_IRUGO, show_fan_alarm, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(fan5_fault, S_IRUGO, show_fan_fault, NULL, 4); -static SENSOR_DEVICE_ATTR(fan6_fault, S_IRUGO, show_fan_fault, NULL, 5); -static SENSOR_DEVICE_ATTR(fan7_fault, S_IRUGO, show_fan_fault, NULL, 6); -static SENSOR_DEVICE_ATTR(fan8_fault, S_IRUGO, show_fan_fault, NULL, 7); - -static struct attribute *pc87427_attributes_fan[8][5] = { - { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - &sensor_dev_attr_fan4_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan5_input.dev_attr.attr, - &sensor_dev_attr_fan5_min.dev_attr.attr, - &sensor_dev_attr_fan5_alarm.dev_attr.attr, - &sensor_dev_attr_fan5_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan6_input.dev_attr.attr, - &sensor_dev_attr_fan6_min.dev_attr.attr, - &sensor_dev_attr_fan6_alarm.dev_attr.attr, - &sensor_dev_attr_fan6_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan7_input.dev_attr.attr, - &sensor_dev_attr_fan7_min.dev_attr.attr, - &sensor_dev_attr_fan7_alarm.dev_attr.attr, - &sensor_dev_attr_fan7_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan8_input.dev_attr.attr, - &sensor_dev_attr_fan8_min.dev_attr.attr, - &sensor_dev_attr_fan8_alarm.dev_attr.attr, - &sensor_dev_attr_fan8_fault.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group pc87427_group_fan[8] = { - { .attrs = pc87427_attributes_fan[0] }, - { .attrs = pc87427_attributes_fan[1] }, - { .attrs = pc87427_attributes_fan[2] }, - { .attrs = pc87427_attributes_fan[3] }, - { .attrs = pc87427_attributes_fan[4] }, - { .attrs = pc87427_attributes_fan[5] }, - { .attrs = pc87427_attributes_fan[6] }, - { .attrs = pc87427_attributes_fan[7] }, -}; - -/* - * Must be called with data->lock held and pc87427_readall_pwm() freshly - * called - */ -static void update_pwm_enable(struct pc87427_data *data, int nr, u8 mode) -{ - int iobase = data->address[LD_FAN]; - data->pwm_enable[nr] &= ~PWM_ENABLE_MODE_MASK; - data->pwm_enable[nr] |= mode; - outb(data->pwm_enable[nr], iobase + PC87427_REG_PWM_ENABLE); -} - -static ssize_t show_pwm_enable(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - int pwm_enable; - - pwm_enable = pwm_enable_from_reg(data->pwm_enable[nr]); - if (pwm_enable < 0) - return pwm_enable; - return sprintf(buf, "%d\n", pwm_enable); -} - -static ssize_t set_pwm_enable(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct pc87427_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0 || val > 2) - return -EINVAL; - /* Can't go to automatic mode if it isn't configured */ - if (val == 2 && !(data->pwm_auto_ok & (1 << nr))) - return -EINVAL; - - mutex_lock(&data->lock); - pc87427_readall_pwm(data, nr); - update_pwm_enable(data, nr, pwm_enable_to_reg(val, data->pwm[nr])); - mutex_unlock(&data->lock); - - return count; -} - -static ssize_t show_pwm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", (int)data->pwm[nr]); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct pc87427_data *data = dev_get_drvdata(dev); - int nr = to_sensor_dev_attr(devattr)->index; - unsigned long val; - int iobase = data->address[LD_FAN]; - u8 mode; - - if (kstrtoul(buf, 10, &val) < 0 || val > 0xff) - return -EINVAL; - - mutex_lock(&data->lock); - pc87427_readall_pwm(data, nr); - mode = data->pwm_enable[nr] & PWM_ENABLE_MODE_MASK; - if (mode != PWM_MODE_MANUAL && mode != PWM_MODE_OFF) { - dev_notice(dev, "Can't set PWM%d duty cycle while not in " - "manual mode\n", nr + 1); - mutex_unlock(&data->lock); - return -EPERM; - } - - /* We may have to change the mode */ - if (mode == PWM_MODE_MANUAL && val == 0) { - /* Transition from Manual to Off */ - update_pwm_enable(data, nr, PWM_MODE_OFF); - mode = PWM_MODE_OFF; - dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1, - "manual", "off"); - } else if (mode == PWM_MODE_OFF && val != 0) { - /* Transition from Off to Manual */ - update_pwm_enable(data, nr, PWM_MODE_MANUAL); - mode = PWM_MODE_MANUAL; - dev_dbg(dev, "Switching PWM%d from %s to %s\n", nr + 1, - "off", "manual"); - } - - data->pwm[nr] = val; - if (mode == PWM_MODE_MANUAL) - outb(val, iobase + PC87427_REG_PWM_DUTY); - mutex_unlock(&data->lock); - - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 2); -static SENSOR_DEVICE_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, - show_pwm_enable, set_pwm_enable, 3); - -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 3); - -static struct attribute *pc87427_attributes_pwm[4][3] = { - { - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_pwm4_enable.dev_attr.attr, - &sensor_dev_attr_pwm4.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group pc87427_group_pwm[4] = { - { .attrs = pc87427_attributes_pwm[0] }, - { .attrs = pc87427_attributes_pwm[1] }, - { .attrs = pc87427_attributes_pwm[2] }, - { .attrs = pc87427_attributes_pwm[3] }, -}; - -static ssize_t show_temp_input(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr])); -} - -static ssize_t show_temp_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_min[nr])); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_max[nr])); -} - -static ssize_t show_temp_crit(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%ld\n", temp_from_reg8(data->temp_crit[nr])); -} - -static ssize_t show_temp_type(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%u\n", temp_type_from_reg(data->temp_type[nr])); -} - -static ssize_t show_temp_min_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", !!(data->temp_status[nr] - & TEMP_STATUS_LOWFLG)); -} - -static ssize_t show_temp_max_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", !!(data->temp_status[nr] - & TEMP_STATUS_HIGHFLG)); -} - -static ssize_t show_temp_crit_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", !!(data->temp_status[nr] - & TEMP_STATUS_CRITFLG)); -} - -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = pc87427_update_device(dev); - int nr = to_sensor_dev_attr(devattr)->index; - - return sprintf(buf, "%d\n", !!(data->temp_status[nr] - & TEMP_STATUS_SENSERR)); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_input, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp_input, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp_input, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_min, S_IRUGO, show_temp_min, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_type, S_IRUGO, show_temp_type, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_type, S_IRUGO, show_temp_type, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_type, S_IRUGO, show_temp_type, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_min_alarm, S_IRUGO, - show_temp_min_alarm, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_max_alarm, S_IRUGO, - show_temp_max_alarm, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_crit_alarm, S_IRUGO, - show_temp_crit_alarm, NULL, 5); - -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); - -static struct attribute *pc87427_attributes_temp[6][10] = { - { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_type.dev_attr.attr, - &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_type.dev_attr.attr, - &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_type.dev_attr.attr, - &sensor_dev_attr_temp3_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_min.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_crit.dev_attr.attr, - &sensor_dev_attr_temp4_type.dev_attr.attr, - &sensor_dev_attr_temp4_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp4_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp5_min.dev_attr.attr, - &sensor_dev_attr_temp5_max.dev_attr.attr, - &sensor_dev_attr_temp5_crit.dev_attr.attr, - &sensor_dev_attr_temp5_type.dev_attr.attr, - &sensor_dev_attr_temp5_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp5_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp5_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp5_fault.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp6_min.dev_attr.attr, - &sensor_dev_attr_temp6_max.dev_attr.attr, - &sensor_dev_attr_temp6_crit.dev_attr.attr, - &sensor_dev_attr_temp6_type.dev_attr.attr, - &sensor_dev_attr_temp6_min_alarm.dev_attr.attr, - &sensor_dev_attr_temp6_max_alarm.dev_attr.attr, - &sensor_dev_attr_temp6_crit_alarm.dev_attr.attr, - &sensor_dev_attr_temp6_fault.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group pc87427_group_temp[6] = { - { .attrs = pc87427_attributes_temp[0] }, - { .attrs = pc87427_attributes_temp[1] }, - { .attrs = pc87427_attributes_temp[2] }, - { .attrs = pc87427_attributes_temp[3] }, - { .attrs = pc87427_attributes_temp[4] }, - { .attrs = pc87427_attributes_temp[5] }, -}; - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct pc87427_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - - -/* - * Device detection, attach and detach - */ - -static void pc87427_release_regions(struct platform_device *pdev, int count) -{ - struct resource *res; - int i; - - for (i = 0; i < count; i++) { - res = platform_get_resource(pdev, IORESOURCE_IO, i); - release_region(res->start, resource_size(res)); - } -} - -static int __devinit pc87427_request_regions(struct platform_device *pdev, - int count) -{ - struct resource *res; - int i, err = 0; - - for (i = 0; i < count; i++) { - res = platform_get_resource(pdev, IORESOURCE_IO, i); - if (!res) { - err = -ENOENT; - dev_err(&pdev->dev, "Missing resource #%d\n", i); - break; - } - if (!request_region(res->start, resource_size(res), DRVNAME)) { - err = -EBUSY; - dev_err(&pdev->dev, - "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, - (unsigned long)res->end); - break; - } - } - - if (err && i) - pc87427_release_regions(pdev, i); - - return err; -} - -static void __devinit pc87427_init_device(struct device *dev) -{ - struct pc87427_sio_data *sio_data = dev->platform_data; - struct pc87427_data *data = dev_get_drvdata(dev); - int i; - u8 reg; - - /* The FMC module should be ready */ - reg = pc87427_read8(data, LD_FAN, PC87427_REG_BANK); - if (!(reg & 0x80)) - dev_warn(dev, "%s module not ready!\n", "FMC"); - - /* Check which fans are enabled */ - for (i = 0; i < 8; i++) { - if (!(sio_data->has_fanin & (1 << i))) /* Not wired */ - continue; - reg = pc87427_read8_bank(data, LD_FAN, BANK_FM(i), - PC87427_REG_FAN_STATUS); - if (reg & FAN_STATUS_MONEN) - data->fan_enabled |= (1 << i); - } - - if (!data->fan_enabled) { - dev_dbg(dev, "Enabling monitoring of all fans\n"); - for (i = 0; i < 8; i++) { - if (!(sio_data->has_fanin & (1 << i))) /* Not wired */ - continue; - pc87427_write8_bank(data, LD_FAN, BANK_FM(i), - PC87427_REG_FAN_STATUS, - FAN_STATUS_MONEN); - } - data->fan_enabled = sio_data->has_fanin; - } - - /* Check which PWM outputs are enabled */ - for (i = 0; i < 4; i++) { - if (!(sio_data->has_fanout & (1 << i))) /* Not wired */ - continue; - reg = pc87427_read8_bank(data, LD_FAN, BANK_FC(i), - PC87427_REG_PWM_ENABLE); - if (reg & PWM_ENABLE_CTLEN) - data->pwm_enabled |= (1 << i); - - /* - * We don't expose an interface to reconfigure the automatic - * fan control mode, so only allow to return to this mode if - * it was originally set. - */ - if ((reg & PWM_ENABLE_MODE_MASK) == PWM_MODE_AUTO) { - dev_dbg(dev, "PWM%d is in automatic control mode\n", - i + 1); - data->pwm_auto_ok |= (1 << i); - } - } - - /* The HMC module should be ready */ - reg = pc87427_read8(data, LD_TEMP, PC87427_REG_BANK); - if (!(reg & 0x80)) - dev_warn(dev, "%s module not ready!\n", "HMC"); - - /* Check which temperature channels are enabled */ - for (i = 0; i < 6; i++) { - reg = pc87427_read8_bank(data, LD_TEMP, BANK_TM(i), - PC87427_REG_TEMP_STATUS); - if (reg & TEMP_STATUS_CHANEN) - data->temp_enabled |= (1 << i); - } -} - -static void pc87427_remove_files(struct device *dev) -{ - struct pc87427_data *data = dev_get_drvdata(dev); - int i; - - device_remove_file(dev, &dev_attr_name); - for (i = 0; i < 8; i++) { - if (!(data->fan_enabled & (1 << i))) - continue; - sysfs_remove_group(&dev->kobj, &pc87427_group_fan[i]); - } - for (i = 0; i < 4; i++) { - if (!(data->pwm_enabled & (1 << i))) - continue; - sysfs_remove_group(&dev->kobj, &pc87427_group_pwm[i]); - } - for (i = 0; i < 6; i++) { - if (!(data->temp_enabled & (1 << i))) - continue; - sysfs_remove_group(&dev->kobj, &pc87427_group_temp[i]); - } -} - -static int __devinit pc87427_probe(struct platform_device *pdev) -{ - struct pc87427_sio_data *sio_data = pdev->dev.platform_data; - struct pc87427_data *data; - int i, err, res_count; - - data = kzalloc(sizeof(struct pc87427_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - pr_err("Out of memory\n"); - goto exit; - } - - data->address[0] = sio_data->address[0]; - data->address[1] = sio_data->address[1]; - res_count = (data->address[0] != 0) + (data->address[1] != 0); - - err = pc87427_request_regions(pdev, res_count); - if (err) - goto exit_kfree; - - mutex_init(&data->lock); - data->name = "pc87427"; - platform_set_drvdata(pdev, data); - pc87427_init_device(&pdev->dev); - - /* Register sysfs hooks */ - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_release_region; - for (i = 0; i < 8; i++) { - if (!(data->fan_enabled & (1 << i))) - continue; - err = sysfs_create_group(&pdev->dev.kobj, - &pc87427_group_fan[i]); - if (err) - goto exit_remove_files; - } - for (i = 0; i < 4; i++) { - if (!(data->pwm_enabled & (1 << i))) - continue; - err = sysfs_create_group(&pdev->dev.kobj, - &pc87427_group_pwm[i]); - if (err) - goto exit_remove_files; - } - for (i = 0; i < 6; i++) { - if (!(data->temp_enabled & (1 << i))) - continue; - err = sysfs_create_group(&pdev->dev.kobj, - &pc87427_group_temp[i]); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - dev_err(&pdev->dev, "Class registration failed (%d)\n", err); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - pc87427_remove_files(&pdev->dev); -exit_release_region: - pc87427_release_regions(pdev, res_count); -exit_kfree: - platform_set_drvdata(pdev, NULL); - kfree(data); -exit: - return err; -} - -static int __devexit pc87427_remove(struct platform_device *pdev) -{ - struct pc87427_data *data = platform_get_drvdata(pdev); - int res_count; - - res_count = (data->address[0] != 0) + (data->address[1] != 0); - - hwmon_device_unregister(data->hwmon_dev); - pc87427_remove_files(&pdev->dev); - platform_set_drvdata(pdev, NULL); - kfree(data); - - pc87427_release_regions(pdev, res_count); - - return 0; -} - - -static struct platform_driver pc87427_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = pc87427_probe, - .remove = __devexit_p(pc87427_remove), -}; - -static int __init pc87427_device_add(const struct pc87427_sio_data *sio_data) -{ - struct resource res[2] = { - { .flags = IORESOURCE_IO }, - { .flags = IORESOURCE_IO }, - }; - int err, i, res_count; - - res_count = 0; - for (i = 0; i < 2; i++) { - if (!sio_data->address[i]) - continue; - res[res_count].start = sio_data->address[i]; - res[res_count].end = sio_data->address[i] + REGION_LENGTH - 1; - res[res_count].name = logdev_str[i]; - - err = acpi_check_resource_conflict(&res[res_count]); - if (err) - goto exit; - - res_count++; - } - - pdev = platform_device_alloc(DRVNAME, res[0].start); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, res, res_count); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add_data(pdev, sio_data, - sizeof(struct pc87427_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init pc87427_find(int sioaddr, struct pc87427_sio_data *sio_data) -{ - u16 val; - u8 cfg, cfg_b; - int i, err = 0; - - /* Identify device */ - val = force_id ? force_id : superio_inb(sioaddr, SIOREG_DEVID); - if (val != 0xf2) { /* PC87427 */ - err = -ENODEV; - goto exit; - } - - for (i = 0; i < 2; i++) { - sio_data->address[i] = 0; - /* Select logical device */ - superio_outb(sioaddr, SIOREG_LDSEL, logdev[i]); - - val = superio_inb(sioaddr, SIOREG_ACT); - if (!(val & 0x01)) { - pr_info("Logical device 0x%02x not activated\n", - logdev[i]); - continue; - } - - val = superio_inb(sioaddr, SIOREG_MAP); - if (val & 0x01) { - pr_warn("Logical device 0x%02x is memory-mapped, " - "can't use\n", logdev[i]); - continue; - } - - val = (superio_inb(sioaddr, SIOREG_IOBASE) << 8) - | superio_inb(sioaddr, SIOREG_IOBASE + 1); - if (!val) { - pr_info("I/O base address not set for logical device " - "0x%02x\n", logdev[i]); - continue; - } - sio_data->address[i] = val; - } - - /* No point in loading the driver if everything is disabled */ - if (!sio_data->address[0] && !sio_data->address[1]) { - err = -ENODEV; - goto exit; - } - - /* Check which fan inputs are wired */ - sio_data->has_fanin = (1 << 2) | (1 << 3); /* FANIN2, FANIN3 */ - - cfg = superio_inb(sioaddr, SIOREG_CF2); - if (!(cfg & (1 << 3))) - sio_data->has_fanin |= (1 << 0); /* FANIN0 */ - if (!(cfg & (1 << 2))) - sio_data->has_fanin |= (1 << 4); /* FANIN4 */ - - cfg = superio_inb(sioaddr, SIOREG_CFD); - if (!(cfg & (1 << 0))) - sio_data->has_fanin |= (1 << 1); /* FANIN1 */ - - cfg = superio_inb(sioaddr, SIOREG_CF4); - if (!(cfg & (1 << 0))) - sio_data->has_fanin |= (1 << 7); /* FANIN7 */ - cfg_b = superio_inb(sioaddr, SIOREG_CFB); - if (!(cfg & (1 << 1)) && (cfg_b & (1 << 3))) - sio_data->has_fanin |= (1 << 5); /* FANIN5 */ - cfg = superio_inb(sioaddr, SIOREG_CF3); - if ((cfg & (1 << 3)) && !(cfg_b & (1 << 5))) - sio_data->has_fanin |= (1 << 6); /* FANIN6 */ - - /* Check which fan outputs are wired */ - sio_data->has_fanout = (1 << 0); /* FANOUT0 */ - if (cfg_b & (1 << 0)) - sio_data->has_fanout |= (1 << 3); /* FANOUT3 */ - - cfg = superio_inb(sioaddr, SIOREG_CFC); - if (!(cfg & (1 << 4))) { - if (cfg_b & (1 << 1)) - sio_data->has_fanout |= (1 << 1); /* FANOUT1 */ - if (cfg_b & (1 << 2)) - sio_data->has_fanout |= (1 << 2); /* FANOUT2 */ - } - - /* FANOUT1 and FANOUT2 can each be routed to 2 different pins */ - cfg = superio_inb(sioaddr, SIOREG_CF5); - if (cfg & (1 << 6)) - sio_data->has_fanout |= (1 << 1); /* FANOUT1 */ - if (cfg & (1 << 5)) - sio_data->has_fanout |= (1 << 2); /* FANOUT2 */ - -exit: - superio_exit(sioaddr); - return err; -} - -static int __init pc87427_init(void) -{ - int err; - struct pc87427_sio_data sio_data; - - if (pc87427_find(0x2e, &sio_data) - && pc87427_find(0x4e, &sio_data)) - return -ENODEV; - - err = platform_driver_register(&pc87427_driver); - if (err) - goto exit; - - /* Sets global pdev as a side effect */ - err = pc87427_device_add(&sio_data); - if (err) - goto exit_driver; - - return 0; - -exit_driver: - platform_driver_unregister(&pc87427_driver); -exit: - return err; -} - -static void __exit pc87427_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&pc87427_driver); -} - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("PC87427 hardware monitoring driver"); -MODULE_LICENSE("GPL"); - -module_init(pc87427_init); -module_exit(pc87427_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/pcf8591.c b/ANDROID_3.4.5/drivers/hwmon/pcf8591.c deleted file mode 100644 index 4174c746..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pcf8591.c +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (C) 2001-2004 Aurelien Jarno - * Ported to Linux 2.6 by Aurelien Jarno with - * the help of Jean Delvare - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include - -/* Insmod parameters */ - -static int input_mode; -module_param(input_mode, int, 0); -MODULE_PARM_DESC(input_mode, - "Analog input mode:\n" - " 0 = four single ended inputs\n" - " 1 = three differential inputs\n" - " 2 = single ended and differential mixed\n" - " 3 = two differential inputs\n"); - -/* - * The PCF8591 control byte - * 7 6 5 4 3 2 1 0 - * | 0 |AOEF| AIP | 0 |AINC| AICH | - */ - -/* Analog Output Enable Flag (analog output active if 1) */ -#define PCF8591_CONTROL_AOEF 0x40 - -/* - * Analog Input Programming - * 0x00 = four single ended inputs - * 0x10 = three differential inputs - * 0x20 = single ended and differential mixed - * 0x30 = two differential inputs - */ -#define PCF8591_CONTROL_AIP_MASK 0x30 - -/* Autoincrement Flag (switch on if 1) */ -#define PCF8591_CONTROL_AINC 0x04 - -/* - * Channel selection - * 0x00 = channel 0 - * 0x01 = channel 1 - * 0x02 = channel 2 - * 0x03 = channel 3 - */ -#define PCF8591_CONTROL_AICH_MASK 0x03 - -/* Initial values */ -#define PCF8591_INIT_CONTROL ((input_mode << 4) | PCF8591_CONTROL_AOEF) -#define PCF8591_INIT_AOUT 0 /* DAC out = 0 */ - -/* Conversions */ -#define REG_TO_SIGNED(reg) (((reg) & 0x80) ? ((reg) - 256) : (reg)) - -struct pcf8591_data { - struct device *hwmon_dev; - struct mutex update_lock; - - u8 control; - u8 aout; -}; - -static void pcf8591_init_client(struct i2c_client *client); -static int pcf8591_read_channel(struct device *dev, int channel); - -/* following are the sysfs callback functions */ -#define show_in_channel(channel) \ -static ssize_t show_in##channel##_input(struct device *dev, \ - struct device_attribute *attr, \ - char *buf) \ -{ \ - return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\ -} \ -static DEVICE_ATTR(in##channel##_input, S_IRUGO, \ - show_in##channel##_input, NULL); - -show_in_channel(0); -show_in_channel(1); -show_in_channel(2); -show_in_channel(3); - -static ssize_t show_out0_ouput(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev)); - return sprintf(buf, "%d\n", data->aout * 10); -} - -static ssize_t set_out0_output(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - unsigned long val; - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - val /= 10; - if (val > 255) - return -EINVAL; - - data->aout = val; - i2c_smbus_write_byte_data(client, data->control, data->aout); - return count; -} - -static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, - show_out0_ouput, set_out0_output); - -static ssize_t show_out0_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev)); - return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF))); -} - -static ssize_t set_out0_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (val) - data->control |= PCF8591_CONTROL_AOEF; - else - data->control &= ~PCF8591_CONTROL_AOEF; - i2c_smbus_write_byte(client, data->control); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, - show_out0_enable, set_out0_enable); - -static struct attribute *pcf8591_attributes[] = { - &dev_attr_out0_enable.attr, - &dev_attr_out0_output.attr, - &dev_attr_in0_input.attr, - &dev_attr_in1_input.attr, - NULL -}; - -static const struct attribute_group pcf8591_attr_group = { - .attrs = pcf8591_attributes, -}; - -static struct attribute *pcf8591_attributes_opt[] = { - &dev_attr_in2_input.attr, - &dev_attr_in3_input.attr, - NULL -}; - -static const struct attribute_group pcf8591_attr_group_opt = { - .attrs = pcf8591_attributes_opt, -}; - -/* - * Real code - */ - -static int pcf8591_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct pcf8591_data *data; - int err; - - data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the PCF8591 chip */ - pcf8591_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group); - if (err) - goto exit_kfree; - - /* Register input2 if not in "two differential inputs" mode */ - if (input_mode != 3) { - err = device_create_file(&client->dev, &dev_attr_in2_input); - if (err) - goto exit_sysfs_remove; - } - - /* Register input3 only in "four single ended inputs" mode */ - if (input_mode == 0) { - err = device_create_file(&client->dev, &dev_attr_in3_input); - if (err) - goto exit_sysfs_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_sysfs_remove; - } - - return 0; - -exit_sysfs_remove: - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); -exit_kfree: - kfree(data); -exit: - return err; -} - -static int pcf8591_remove(struct i2c_client *client) -{ - struct pcf8591_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt); - sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group); - kfree(i2c_get_clientdata(client)); - return 0; -} - -/* Called when we have found a new PCF8591. */ -static void pcf8591_init_client(struct i2c_client *client) -{ - struct pcf8591_data *data = i2c_get_clientdata(client); - data->control = PCF8591_INIT_CONTROL; - data->aout = PCF8591_INIT_AOUT; - - i2c_smbus_write_byte_data(client, data->control, data->aout); - - /* - * The first byte transmitted contains the conversion code of the - * previous read cycle. FLUSH IT! - */ - i2c_smbus_read_byte(client); -} - -static int pcf8591_read_channel(struct device *dev, int channel) -{ - u8 value; - struct i2c_client *client = to_i2c_client(dev); - struct pcf8591_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) { - data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK) - | channel; - i2c_smbus_write_byte(client, data->control); - - /* - * The first byte transmitted contains the conversion code of - * the previous read cycle. FLUSH IT! - */ - i2c_smbus_read_byte(client); - } - value = i2c_smbus_read_byte(client); - - mutex_unlock(&data->update_lock); - - if ((channel == 2 && input_mode == 2) || - (channel != 3 && (input_mode == 1 || input_mode == 3))) - return 10 * REG_TO_SIGNED(value); - else - return 10 * value; -} - -static const struct i2c_device_id pcf8591_id[] = { - { "pcf8591", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, pcf8591_id); - -static struct i2c_driver pcf8591_driver = { - .driver = { - .name = "pcf8591", - }, - .probe = pcf8591_probe, - .remove = pcf8591_remove, - .id_table = pcf8591_id, -}; - -static int __init pcf8591_init(void) -{ - if (input_mode < 0 || input_mode > 3) { - pr_warn("invalid input_mode (%d)\n", input_mode); - input_mode = 0; - } - return i2c_add_driver(&pcf8591_driver); -} - -static void __exit pcf8591_exit(void) -{ - i2c_del_driver(&pcf8591_driver); -} - -MODULE_AUTHOR("Aurelien Jarno "); -MODULE_DESCRIPTION("PCF8591 driver"); -MODULE_LICENSE("GPL"); - -module_init(pcf8591_init); -module_exit(pcf8591_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/Kconfig b/ANDROID_3.4.5/drivers/hwmon/pmbus/Kconfig deleted file mode 100644 index 2ca6a5a4..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/Kconfig +++ /dev/null @@ -1,124 +0,0 @@ -# -# PMBus chip drivers configuration -# - -menuconfig PMBUS - tristate "PMBus support" - depends on I2C && EXPERIMENTAL - default n - help - Say yes here if you want to enable PMBus support. - - This driver can also be built as a module. If so, the module will - be called pmbus_core. - -if PMBUS - -config SENSORS_PMBUS - tristate "Generic PMBus devices" - default y - help - If you say yes here you get hardware monitoring support for generic - PMBus devices, including but not limited to ADP4000, BMR453, BMR454, - MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, TPS40400, - and TPS40422. - - This driver can also be built as a module. If so, the module will - be called pmbus. - -config SENSORS_ADM1275 - tristate "Analog Devices ADM1275 and compatibles" - default n - help - If you say yes here you get hardware monitoring support for Analog - Devices ADM1075, ADM1275, and ADM1276 Hot-Swap Controller and Digital - Power Monitors. - - This driver can also be built as a module. If so, the module will - be called adm1275. - -config SENSORS_LM25066 - tristate "National Semiconductor LM25066 and compatibles" - default n - help - If you say yes here you get hardware monitoring support for National - Semiconductor LM25066, LM5064, and LM5066. - - This driver can also be built as a module. If so, the module will - be called lm25066. - -config SENSORS_LTC2978 - tristate "Linear Technologies LTC2978 and LTC3880" - default n - help - If you say yes here you get hardware monitoring support for Linear - Technology LTC2978 and LTC3880. - - This driver can also be built as a module. If so, the module will - be called ltc2978. - -config SENSORS_MAX16064 - tristate "Maxim MAX16064" - default n - help - If you say yes here you get hardware monitoring support for Maxim - MAX16064. - - This driver can also be built as a module. If so, the module will - be called max16064. - -config SENSORS_MAX34440 - tristate "Maxim MAX34440 and compatibles" - default n - help - If you say yes here you get hardware monitoring support for Maxim - MAX34440, MAX34441, and MAX34446. - - This driver can also be built as a module. If so, the module will - be called max34440. - -config SENSORS_MAX8688 - tristate "Maxim MAX8688" - default n - help - If you say yes here you get hardware monitoring support for Maxim - MAX8688. - - This driver can also be built as a module. If so, the module will - be called max8688. - -config SENSORS_UCD9000 - tristate "TI UCD90120, UCD90124, UCD9090, UCD90910" - default n - help - If you say yes here you get hardware monitoring support for TI - UCD90120, UCD90124, UCD9090, UCD90910 Sequencer and System Health - Controllers. - - This driver can also be built as a module. If so, the module will - be called ucd9000. - -config SENSORS_UCD9200 - tristate "TI UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, UCD9248" - default n - help - If you say yes here you get hardware monitoring support for TI - UCD9220, UCD9222, UCD9224, UCD9240, UCD9244, UCD9246, and UCD9248 - Digital PWM System Controllers. - - This driver can also be built as a module. If so, the module will - be called ucd9200. - -config SENSORS_ZL6100 - tristate "Intersil ZL6100 and compatibles" - default n - help - If you say yes here you get hardware monitoring support for Intersil - ZL2004, ZL2005, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, ZL6105, - ZL9101M, and ZL9117M Digital DC/DC Controllers, as well as for - Ericsson BMR450, BMR451, BMR462, BMR463, and BMR464. - - This driver can also be built as a module. If so, the module will - be called zl6100. - -endif # PMBUS diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/Makefile b/ANDROID_3.4.5/drivers/hwmon/pmbus/Makefile deleted file mode 100644 index 789376c8..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/Makefile +++ /dev/null @@ -1,15 +0,0 @@ -# -# Makefile for PMBus chip drivers. -# - -obj-$(CONFIG_PMBUS) += pmbus_core.o -obj-$(CONFIG_SENSORS_PMBUS) += pmbus.o -obj-$(CONFIG_SENSORS_ADM1275) += adm1275.o -obj-$(CONFIG_SENSORS_LM25066) += lm25066.o -obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o -obj-$(CONFIG_SENSORS_MAX16064) += max16064.o -obj-$(CONFIG_SENSORS_MAX34440) += max34440.o -obj-$(CONFIG_SENSORS_MAX8688) += max8688.o -obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o -obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o -obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/adm1275.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/adm1275.c deleted file mode 100644 index 60aad957..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/adm1275.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * Hardware monitoring driver for Analog Devices ADM1275 Hot-Swap Controller - * and Digital Power Monitor - * - * Copyright (c) 2011 Ericsson AB. - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -enum chips { adm1075, adm1275, adm1276 }; - -#define ADM1275_PEAK_IOUT 0xd0 -#define ADM1275_PEAK_VIN 0xd1 -#define ADM1275_PEAK_VOUT 0xd2 -#define ADM1275_PMON_CONFIG 0xd4 - -#define ADM1275_VIN_VOUT_SELECT (1 << 6) -#define ADM1275_VRANGE (1 << 5) -#define ADM1075_IRANGE_50 (1 << 4) -#define ADM1075_IRANGE_25 (1 << 3) -#define ADM1075_IRANGE_MASK ((1 << 3) | (1 << 4)) - -#define ADM1275_IOUT_WARN2_LIMIT 0xd7 -#define ADM1275_DEVICE_CONFIG 0xd8 - -#define ADM1275_IOUT_WARN2_SELECT (1 << 4) - -#define ADM1276_PEAK_PIN 0xda - -#define ADM1275_MFR_STATUS_IOUT_WARN2 (1 << 0) - -#define ADM1075_READ_VAUX 0xdd -#define ADM1075_VAUX_OV_WARN_LIMIT 0xde -#define ADM1075_VAUX_UV_WARN_LIMIT 0xdf -#define ADM1075_VAUX_STATUS 0xf6 - -#define ADM1075_VAUX_OV_WARN (1<<7) -#define ADM1075_VAUX_UV_WARN (1<<6) - -struct adm1275_data { - int id; - bool have_oc_fault; - struct pmbus_driver_info info; -}; - -#define to_adm1275_data(x) container_of(x, struct adm1275_data, info) - -static int adm1275_read_word_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - const struct adm1275_data *data = to_adm1275_data(info); - int ret = 0; - - if (page) - return -ENXIO; - - switch (reg) { - case PMBUS_IOUT_UC_FAULT_LIMIT: - if (data->have_oc_fault) { - ret = -ENXIO; - break; - } - ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); - break; - case PMBUS_IOUT_OC_FAULT_LIMIT: - if (!data->have_oc_fault) { - ret = -ENXIO; - break; - } - ret = pmbus_read_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT); - break; - case PMBUS_VOUT_OV_WARN_LIMIT: - if (data->id != adm1075) { - ret = -ENODATA; - break; - } - ret = pmbus_read_word_data(client, 0, - ADM1075_VAUX_OV_WARN_LIMIT); - break; - case PMBUS_VOUT_UV_WARN_LIMIT: - if (data->id != adm1075) { - ret = -ENODATA; - break; - } - ret = pmbus_read_word_data(client, 0, - ADM1075_VAUX_UV_WARN_LIMIT); - break; - case PMBUS_READ_VOUT: - if (data->id != adm1075) { - ret = -ENODATA; - break; - } - ret = pmbus_read_word_data(client, 0, ADM1075_READ_VAUX); - break; - case PMBUS_VIRT_READ_IOUT_MAX: - ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_IOUT); - break; - case PMBUS_VIRT_READ_VOUT_MAX: - ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VOUT); - break; - case PMBUS_VIRT_READ_VIN_MAX: - ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN); - break; - case PMBUS_VIRT_READ_PIN_MAX: - if (data->id == adm1275) { - ret = -ENXIO; - break; - } - ret = pmbus_read_word_data(client, 0, ADM1276_PEAK_PIN); - break; - case PMBUS_VIRT_RESET_IOUT_HISTORY: - case PMBUS_VIRT_RESET_VOUT_HISTORY: - case PMBUS_VIRT_RESET_VIN_HISTORY: - break; - case PMBUS_VIRT_RESET_PIN_HISTORY: - if (data->id == adm1275) - ret = -ENXIO; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int adm1275_write_word_data(struct i2c_client *client, int page, int reg, - u16 word) -{ - int ret; - - if (page) - return -ENXIO; - - switch (reg) { - case PMBUS_IOUT_UC_FAULT_LIMIT: - case PMBUS_IOUT_OC_FAULT_LIMIT: - ret = pmbus_write_word_data(client, 0, ADM1275_IOUT_WARN2_LIMIT, - word); - break; - case PMBUS_VIRT_RESET_IOUT_HISTORY: - ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_IOUT, 0); - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VOUT, 0); - break; - case PMBUS_VIRT_RESET_VIN_HISTORY: - ret = pmbus_write_word_data(client, 0, ADM1275_PEAK_VIN, 0); - break; - case PMBUS_VIRT_RESET_PIN_HISTORY: - ret = pmbus_write_word_data(client, 0, ADM1276_PEAK_PIN, 0); - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - const struct adm1275_data *data = to_adm1275_data(info); - int mfr_status, ret; - - if (page > 0) - return -ENXIO; - - switch (reg) { - case PMBUS_STATUS_IOUT: - ret = pmbus_read_byte_data(client, page, PMBUS_STATUS_IOUT); - if (ret < 0) - break; - mfr_status = pmbus_read_byte_data(client, page, - PMBUS_STATUS_MFR_SPECIFIC); - if (mfr_status < 0) { - ret = mfr_status; - break; - } - if (mfr_status & ADM1275_MFR_STATUS_IOUT_WARN2) { - ret |= data->have_oc_fault ? - PB_IOUT_OC_FAULT : PB_IOUT_UC_FAULT; - } - break; - case PMBUS_STATUS_VOUT: - if (data->id != adm1075) { - ret = -ENODATA; - break; - } - ret = 0; - mfr_status = pmbus_read_byte_data(client, 0, - ADM1075_VAUX_STATUS); - if (mfr_status & ADM1075_VAUX_OV_WARN) - ret |= PB_VOLTAGE_OV_WARNING; - if (mfr_status & ADM1075_VAUX_UV_WARN) - ret |= PB_VOLTAGE_UV_WARNING; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static const struct i2c_device_id adm1275_id[] = { - { "adm1075", adm1075 }, - { "adm1275", adm1275 }, - { "adm1276", adm1276 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1275_id); - -static int adm1275_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; - int config, device_config; - int ret; - struct pmbus_driver_info *info; - struct adm1275_data *data; - const struct i2c_device_id *mid; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA - | I2C_FUNC_SMBUS_BLOCK_DATA)) - return -ENODEV; - - ret = i2c_smbus_read_block_data(client, PMBUS_MFR_ID, block_buffer); - if (ret < 0) { - dev_err(&client->dev, "Failed to read Manufacturer ID\n"); - return ret; - } - if (ret != 3 || strncmp(block_buffer, "ADI", 3)) { - dev_err(&client->dev, "Unsupported Manufacturer ID\n"); - return -ENODEV; - } - - ret = i2c_smbus_read_block_data(client, PMBUS_MFR_MODEL, block_buffer); - if (ret < 0) { - dev_err(&client->dev, "Failed to read Manufacturer Model\n"); - return ret; - } - for (mid = adm1275_id; mid->name[0]; mid++) { - if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) - break; - } - if (!mid->name[0]) { - dev_err(&client->dev, "Unsupported device\n"); - return -ENODEV; - } - - if (id->driver_data != mid->driver_data) - dev_notice(&client->dev, - "Device mismatch: Configured %s, detected %s\n", - id->name, mid->name); - - config = i2c_smbus_read_byte_data(client, ADM1275_PMON_CONFIG); - if (config < 0) - return config; - - device_config = i2c_smbus_read_byte_data(client, ADM1275_DEVICE_CONFIG); - if (device_config < 0) - return device_config; - - data = devm_kzalloc(&client->dev, sizeof(struct adm1275_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->id = mid->driver_data; - - info = &data->info; - - info->pages = 1; - info->format[PSC_VOLTAGE_IN] = direct; - info->format[PSC_VOLTAGE_OUT] = direct; - info->format[PSC_CURRENT_OUT] = direct; - info->m[PSC_CURRENT_OUT] = 807; - info->b[PSC_CURRENT_OUT] = 20475; - info->R[PSC_CURRENT_OUT] = -1; - info->func[0] = PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT; - - info->read_word_data = adm1275_read_word_data; - info->read_byte_data = adm1275_read_byte_data; - info->write_word_data = adm1275_write_word_data; - - if (data->id == adm1075) { - info->m[PSC_VOLTAGE_IN] = 27169; - info->b[PSC_VOLTAGE_IN] = 0; - info->R[PSC_VOLTAGE_IN] = -1; - info->m[PSC_VOLTAGE_OUT] = 27169; - info->b[PSC_VOLTAGE_OUT] = 0; - info->R[PSC_VOLTAGE_OUT] = -1; - } else if (config & ADM1275_VRANGE) { - info->m[PSC_VOLTAGE_IN] = 19199; - info->b[PSC_VOLTAGE_IN] = 0; - info->R[PSC_VOLTAGE_IN] = -2; - info->m[PSC_VOLTAGE_OUT] = 19199; - info->b[PSC_VOLTAGE_OUT] = 0; - info->R[PSC_VOLTAGE_OUT] = -2; - } else { - info->m[PSC_VOLTAGE_IN] = 6720; - info->b[PSC_VOLTAGE_IN] = 0; - info->R[PSC_VOLTAGE_IN] = -1; - info->m[PSC_VOLTAGE_OUT] = 6720; - info->b[PSC_VOLTAGE_OUT] = 0; - info->R[PSC_VOLTAGE_OUT] = -1; - } - - if (device_config & ADM1275_IOUT_WARN2_SELECT) - data->have_oc_fault = true; - - switch (data->id) { - case adm1075: - info->format[PSC_POWER] = direct; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -1; - switch (config & ADM1075_IRANGE_MASK) { - case ADM1075_IRANGE_25: - info->m[PSC_POWER] = 8549; - info->m[PSC_CURRENT_OUT] = 806; - break; - case ADM1075_IRANGE_50: - info->m[PSC_POWER] = 4279; - info->m[PSC_CURRENT_OUT] = 404; - break; - default: - dev_err(&client->dev, "Invalid input current range"); - info->m[PSC_POWER] = 0; - info->m[PSC_CURRENT_OUT] = 0; - break; - } - info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN - | PMBUS_HAVE_STATUS_INPUT; - if (config & ADM1275_VIN_VOUT_SELECT) - info->func[0] |= - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; - break; - case adm1275: - if (config & ADM1275_VIN_VOUT_SELECT) - info->func[0] |= - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; - else - info->func[0] |= - PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT; - break; - case adm1276: - info->format[PSC_POWER] = direct; - info->func[0] |= PMBUS_HAVE_VIN | PMBUS_HAVE_PIN - | PMBUS_HAVE_STATUS_INPUT; - if (config & ADM1275_VIN_VOUT_SELECT) - info->func[0] |= - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT; - if (config & ADM1275_VRANGE) { - info->m[PSC_POWER] = 6043; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -2; - } else { - info->m[PSC_POWER] = 2115; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -1; - } - break; - } - - return pmbus_do_probe(client, id, info); -} - -static struct i2c_driver adm1275_driver = { - .driver = { - .name = "adm1275", - }, - .probe = adm1275_probe, - .remove = pmbus_do_remove, - .id_table = adm1275_id, -}; - -module_i2c_driver(adm1275_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/lm25066.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/lm25066.c deleted file mode 100644 index c2993927..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/lm25066.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Hardware monitoring driver for LM25066 / LM5064 / LM5066 - * - * Copyright (c) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -enum chips { lm25066, lm5064, lm5066 }; - -#define LM25066_READ_VAUX 0xd0 -#define LM25066_MFR_READ_IIN 0xd1 -#define LM25066_MFR_READ_PIN 0xd2 -#define LM25066_MFR_IIN_OC_WARN_LIMIT 0xd3 -#define LM25066_MFR_PIN_OP_WARN_LIMIT 0xd4 -#define LM25066_READ_PIN_PEAK 0xd5 -#define LM25066_CLEAR_PIN_PEAK 0xd6 -#define LM25066_DEVICE_SETUP 0xd9 -#define LM25066_READ_AVG_VIN 0xdc -#define LM25066_READ_AVG_VOUT 0xdd -#define LM25066_READ_AVG_IIN 0xde -#define LM25066_READ_AVG_PIN 0xdf - -#define LM25066_DEV_SETUP_CL (1 << 4) /* Current limit */ - -struct lm25066_data { - int id; - struct pmbus_driver_info info; -}; - -#define to_lm25066_data(x) container_of(x, struct lm25066_data, info) - -static int lm25066_read_word_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - const struct lm25066_data *data = to_lm25066_data(info); - int ret; - - if (page > 1) - return -ENXIO; - - /* Map READ_VAUX into READ_VOUT register on page 1 */ - if (page == 1) { - switch (reg) { - case PMBUS_READ_VOUT: - ret = pmbus_read_word_data(client, 0, - LM25066_READ_VAUX); - if (ret < 0) - break; - /* Adjust returned value to match VOUT coefficients */ - switch (data->id) { - case lm25066: - /* VOUT: 4.54 mV VAUX: 283.2 uV LSB */ - ret = DIV_ROUND_CLOSEST(ret * 2832, 45400); - break; - case lm5064: - /* VOUT: 4.53 mV VAUX: 700 uV LSB */ - ret = DIV_ROUND_CLOSEST(ret * 70, 453); - break; - case lm5066: - /* VOUT: 2.18 mV VAUX: 725 uV LSB */ - ret = DIV_ROUND_CLOSEST(ret * 725, 2180); - break; - } - break; - default: - /* No other valid registers on page 1 */ - ret = -ENXIO; - break; - } - goto done; - } - - switch (reg) { - case PMBUS_READ_IIN: - ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_IIN); - break; - case PMBUS_READ_PIN: - ret = pmbus_read_word_data(client, 0, LM25066_MFR_READ_PIN); - break; - case PMBUS_IIN_OC_WARN_LIMIT: - ret = pmbus_read_word_data(client, 0, - LM25066_MFR_IIN_OC_WARN_LIMIT); - break; - case PMBUS_PIN_OP_WARN_LIMIT: - ret = pmbus_read_word_data(client, 0, - LM25066_MFR_PIN_OP_WARN_LIMIT); - break; - case PMBUS_VIRT_READ_VIN_AVG: - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VIN); - break; - case PMBUS_VIRT_READ_VOUT_AVG: - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_VOUT); - break; - case PMBUS_VIRT_READ_IIN_AVG: - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_IIN); - break; - case PMBUS_VIRT_READ_PIN_AVG: - ret = pmbus_read_word_data(client, 0, LM25066_READ_AVG_PIN); - break; - case PMBUS_VIRT_READ_PIN_MAX: - ret = pmbus_read_word_data(client, 0, LM25066_READ_PIN_PEAK); - break; - case PMBUS_VIRT_RESET_PIN_HISTORY: - ret = 0; - break; - default: - ret = -ENODATA; - break; - } -done: - return ret; -} - -static int lm25066_write_word_data(struct i2c_client *client, int page, int reg, - u16 word) -{ - int ret; - - if (page > 1) - return -ENXIO; - - switch (reg) { - case PMBUS_IIN_OC_WARN_LIMIT: - ret = pmbus_write_word_data(client, 0, - LM25066_MFR_IIN_OC_WARN_LIMIT, - word); - break; - case PMBUS_PIN_OP_WARN_LIMIT: - ret = pmbus_write_word_data(client, 0, - LM25066_MFR_PIN_OP_WARN_LIMIT, - word); - break; - case PMBUS_VIRT_RESET_PIN_HISTORY: - ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK); - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int lm25066_write_byte(struct i2c_client *client, int page, u8 value) -{ - if (page > 1) - return -ENXIO; - - if (page <= 0) - return pmbus_write_byte(client, page, value); - - return 0; -} - -static int lm25066_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int config; - struct lm25066_data *data; - struct pmbus_driver_info *info; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_BYTE_DATA)) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP); - if (config < 0) - return config; - - data->id = id->driver_data; - info = &data->info; - - info->pages = 2; - info->format[PSC_VOLTAGE_IN] = direct; - info->format[PSC_VOLTAGE_OUT] = direct; - info->format[PSC_CURRENT_IN] = direct; - info->format[PSC_TEMPERATURE] = direct; - info->format[PSC_POWER] = direct; - - info->m[PSC_TEMPERATURE] = 16; - info->b[PSC_TEMPERATURE] = 0; - info->R[PSC_TEMPERATURE] = 0; - - info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VOUT - | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN - | PMBUS_HAVE_STATUS_INPUT | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - info->func[1] = PMBUS_HAVE_VOUT; - - info->read_word_data = lm25066_read_word_data; - info->write_word_data = lm25066_write_word_data; - info->write_byte = lm25066_write_byte; - - switch (id->driver_data) { - case lm25066: - info->m[PSC_VOLTAGE_IN] = 22070; - info->b[PSC_VOLTAGE_IN] = 0; - info->R[PSC_VOLTAGE_IN] = -2; - info->m[PSC_VOLTAGE_OUT] = 22070; - info->b[PSC_VOLTAGE_OUT] = 0; - info->R[PSC_VOLTAGE_OUT] = -2; - - if (config & LM25066_DEV_SETUP_CL) { - info->m[PSC_CURRENT_IN] = 6852; - info->b[PSC_CURRENT_IN] = 0; - info->R[PSC_CURRENT_IN] = -2; - info->m[PSC_POWER] = 369; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -2; - } else { - info->m[PSC_CURRENT_IN] = 13661; - info->b[PSC_CURRENT_IN] = 0; - info->R[PSC_CURRENT_IN] = -2; - info->m[PSC_POWER] = 736; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -2; - } - break; - case lm5064: - info->m[PSC_VOLTAGE_IN] = 22075; - info->b[PSC_VOLTAGE_IN] = 0; - info->R[PSC_VOLTAGE_IN] = -2; - info->m[PSC_VOLTAGE_OUT] = 22075; - info->b[PSC_VOLTAGE_OUT] = 0; - info->R[PSC_VOLTAGE_OUT] = -2; - - if (config & LM25066_DEV_SETUP_CL) { - info->m[PSC_CURRENT_IN] = 6713; - info->b[PSC_CURRENT_IN] = 0; - info->R[PSC_CURRENT_IN] = -2; - info->m[PSC_POWER] = 3619; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -3; - } else { - info->m[PSC_CURRENT_IN] = 13426; - info->b[PSC_CURRENT_IN] = 0; - info->R[PSC_CURRENT_IN] = -2; - info->m[PSC_POWER] = 7238; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -3; - } - break; - case lm5066: - info->m[PSC_VOLTAGE_IN] = 4587; - info->b[PSC_VOLTAGE_IN] = 0; - info->R[PSC_VOLTAGE_IN] = -2; - info->m[PSC_VOLTAGE_OUT] = 4587; - info->b[PSC_VOLTAGE_OUT] = 0; - info->R[PSC_VOLTAGE_OUT] = -2; - - if (config & LM25066_DEV_SETUP_CL) { - info->m[PSC_CURRENT_IN] = 10753; - info->b[PSC_CURRENT_IN] = 0; - info->R[PSC_CURRENT_IN] = -2; - info->m[PSC_POWER] = 1204; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -3; - } else { - info->m[PSC_CURRENT_IN] = 5405; - info->b[PSC_CURRENT_IN] = 0; - info->R[PSC_CURRENT_IN] = -2; - info->m[PSC_POWER] = 605; - info->b[PSC_POWER] = 0; - info->R[PSC_POWER] = -3; - } - break; - default: - return -ENODEV; - } - - return pmbus_do_probe(client, id, info); -} - -static const struct i2c_device_id lm25066_id[] = { - {"lm25066", lm25066}, - {"lm5064", lm5064}, - {"lm5066", lm5066}, - { } -}; - -MODULE_DEVICE_TABLE(i2c, lm25066_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver lm25066_driver = { - .driver = { - .name = "lm25066", - }, - .probe = lm25066_probe, - .remove = pmbus_do_remove, - .id_table = lm25066_id, -}; - -module_i2c_driver(lm25066_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/ltc2978.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/ltc2978.c deleted file mode 100644 index 9652a2c9..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/ltc2978.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * Hardware monitoring driver for LTC2978 and LTC3880 - * - * Copyright (c) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -enum chips { ltc2978, ltc3880 }; - -/* LTC2978 and LTC3880 */ -#define LTC2978_MFR_VOUT_PEAK 0xdd -#define LTC2978_MFR_VIN_PEAK 0xde -#define LTC2978_MFR_TEMPERATURE_PEAK 0xdf -#define LTC2978_MFR_SPECIAL_ID 0xe7 - -/* LTC2978 only */ -#define LTC2978_MFR_VOUT_MIN 0xfb -#define LTC2978_MFR_VIN_MIN 0xfc -#define LTC2978_MFR_TEMPERATURE_MIN 0xfd - -/* LTC3880 only */ -#define LTC3880_MFR_IOUT_PEAK 0xd7 -#define LTC3880_MFR_CLEAR_PEAKS 0xe3 -#define LTC3880_MFR_TEMPERATURE2_PEAK 0xf4 - -#define LTC2978_ID_REV1 0x0121 -#define LTC2978_ID_REV2 0x0122 -#define LTC3880_ID 0x4000 -#define LTC3880_ID_MASK 0xff00 - -/* - * LTC2978 clears peak data whenever the CLEAR_FAULTS command is executed, which - * happens pretty much each time chip data is updated. Raw peak data therefore - * does not provide much value. To be able to provide useful peak data, keep an - * internal cache of measured peak data, which is only cleared if an explicit - * "clear peak" command is executed for the sensor in question. - */ -struct ltc2978_data { - enum chips id; - int vin_min, vin_max; - int temp_min, temp_max; - int vout_min[8], vout_max[8]; - int iout_max[2]; - int temp2_max[2]; - struct pmbus_driver_info info; -}; - -#define to_ltc2978_data(x) container_of(x, struct ltc2978_data, info) - -static inline int lin11_to_val(int data) -{ - s16 e = ((s16)data) >> 11; - s32 m = (((s16)(data << 5)) >> 5); - - /* - * mantissa is 10 bit + sign, exponent adds up to 15 bit. - * Add 6 bit to exponent for maximum accuracy (10 + 15 + 6 = 31). - */ - e += 6; - return (e < 0 ? m >> -e : m << e); -} - -static int ltc2978_read_word_data_common(struct i2c_client *client, int page, - int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct ltc2978_data *data = to_ltc2978_data(info); - int ret; - - switch (reg) { - case PMBUS_VIRT_READ_VIN_MAX: - ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_PEAK); - if (ret >= 0) { - if (lin11_to_val(ret) > lin11_to_val(data->vin_max)) - data->vin_max = ret; - ret = data->vin_max; - } - break; - case PMBUS_VIRT_READ_VOUT_MAX: - ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_PEAK); - if (ret >= 0) { - /* - * VOUT is 16 bit unsigned with fixed exponent, - * so we can compare it directly - */ - if (ret > data->vout_max[page]) - data->vout_max[page] = ret; - ret = data->vout_max[page]; - } - break; - case PMBUS_VIRT_READ_TEMP_MAX: - ret = pmbus_read_word_data(client, page, - LTC2978_MFR_TEMPERATURE_PEAK); - if (ret >= 0) { - if (lin11_to_val(ret) > lin11_to_val(data->temp_max)) - data->temp_max = ret; - ret = data->temp_max; - } - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - case PMBUS_VIRT_RESET_VIN_HISTORY: - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = 0; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int ltc2978_read_word_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct ltc2978_data *data = to_ltc2978_data(info); - int ret; - - switch (reg) { - case PMBUS_VIRT_READ_VIN_MIN: - ret = pmbus_read_word_data(client, page, LTC2978_MFR_VIN_MIN); - if (ret >= 0) { - if (lin11_to_val(ret) < lin11_to_val(data->vin_min)) - data->vin_min = ret; - ret = data->vin_min; - } - break; - case PMBUS_VIRT_READ_VOUT_MIN: - ret = pmbus_read_word_data(client, page, LTC2978_MFR_VOUT_MIN); - if (ret >= 0) { - /* - * VOUT_MIN is known to not be supported on some lots - * of LTC2978 revision 1, and will return the maximum - * possible voltage if read. If VOUT_MAX is valid and - * lower than the reading of VOUT_MIN, use it instead. - */ - if (data->vout_max[page] && ret > data->vout_max[page]) - ret = data->vout_max[page]; - if (ret < data->vout_min[page]) - data->vout_min[page] = ret; - ret = data->vout_min[page]; - } - break; - case PMBUS_VIRT_READ_TEMP_MIN: - ret = pmbus_read_word_data(client, page, - LTC2978_MFR_TEMPERATURE_MIN); - if (ret >= 0) { - if (lin11_to_val(ret) - < lin11_to_val(data->temp_min)) - data->temp_min = ret; - ret = data->temp_min; - } - break; - case PMBUS_VIRT_READ_IOUT_MAX: - case PMBUS_VIRT_RESET_IOUT_HISTORY: - case PMBUS_VIRT_READ_TEMP2_MAX: - case PMBUS_VIRT_RESET_TEMP2_HISTORY: - ret = -ENXIO; - break; - default: - ret = ltc2978_read_word_data_common(client, page, reg); - break; - } - return ret; -} - -static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct ltc2978_data *data = to_ltc2978_data(info); - int ret; - - switch (reg) { - case PMBUS_VIRT_READ_IOUT_MAX: - ret = pmbus_read_word_data(client, page, LTC3880_MFR_IOUT_PEAK); - if (ret >= 0) { - if (lin11_to_val(ret) - > lin11_to_val(data->iout_max[page])) - data->iout_max[page] = ret; - ret = data->iout_max[page]; - } - break; - case PMBUS_VIRT_READ_TEMP2_MAX: - ret = pmbus_read_word_data(client, page, - LTC3880_MFR_TEMPERATURE2_PEAK); - if (ret >= 0) { - if (lin11_to_val(ret) - > lin11_to_val(data->temp2_max[page])) - data->temp2_max[page] = ret; - ret = data->temp2_max[page]; - } - break; - case PMBUS_VIRT_READ_VIN_MIN: - case PMBUS_VIRT_READ_VOUT_MIN: - case PMBUS_VIRT_READ_TEMP_MIN: - ret = -ENXIO; - break; - case PMBUS_VIRT_RESET_IOUT_HISTORY: - case PMBUS_VIRT_RESET_TEMP2_HISTORY: - ret = 0; - break; - default: - ret = ltc2978_read_word_data_common(client, page, reg); - break; - } - return ret; -} - -static int ltc2978_clear_peaks(struct i2c_client *client, int page, - enum chips id) -{ - int ret; - - if (id == ltc2978) - ret = pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); - else - ret = pmbus_write_byte(client, 0, LTC3880_MFR_CLEAR_PEAKS); - - return ret; -} - -static int ltc2978_write_word_data(struct i2c_client *client, int page, - int reg, u16 word) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct ltc2978_data *data = to_ltc2978_data(info); - int ret; - - switch (reg) { - case PMBUS_VIRT_RESET_IOUT_HISTORY: - data->iout_max[page] = 0x7fff; - ret = ltc2978_clear_peaks(client, page, data->id); - break; - case PMBUS_VIRT_RESET_TEMP2_HISTORY: - data->temp2_max[page] = 0x7fff; - ret = ltc2978_clear_peaks(client, page, data->id); - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - data->vout_min[page] = 0xffff; - data->vout_max[page] = 0; - ret = ltc2978_clear_peaks(client, page, data->id); - break; - case PMBUS_VIRT_RESET_VIN_HISTORY: - data->vin_min = 0x7bff; - data->vin_max = 0; - ret = ltc2978_clear_peaks(client, page, data->id); - break; - case PMBUS_VIRT_RESET_TEMP_HISTORY: - data->temp_min = 0x7bff; - data->temp_max = 0x7fff; - ret = ltc2978_clear_peaks(client, page, data->id); - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static const struct i2c_device_id ltc2978_id[] = { - {"ltc2978", ltc2978}, - {"ltc3880", ltc3880}, - {} -}; -MODULE_DEVICE_TABLE(i2c, ltc2978_id); - -static int ltc2978_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int chip_id, i; - struct ltc2978_data *data; - struct pmbus_driver_info *info; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA)) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(struct ltc2978_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - chip_id = i2c_smbus_read_word_data(client, LTC2978_MFR_SPECIAL_ID); - if (chip_id < 0) - return chip_id; - - if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) { - data->id = ltc2978; - } else if ((chip_id & LTC3880_ID_MASK) == LTC3880_ID) { - data->id = ltc3880; - } else { - dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id); - return -ENODEV; - } - if (data->id != id->driver_data) - dev_warn(&client->dev, - "Device mismatch: Configured %s, detected %s\n", - id->name, - ltc2978_id[data->id].name); - - info = &data->info; - info->write_word_data = ltc2978_write_word_data; - - data->vout_min[0] = 0xffff; - data->vin_min = 0x7bff; - data->temp_min = 0x7bff; - data->temp_max = 0x7fff; - - switch (id->driver_data) { - case ltc2978: - info->read_word_data = ltc2978_read_word_data; - info->pages = 8; - info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT - | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - for (i = 1; i < 8; i++) { - info->func[i] = PMBUS_HAVE_VOUT - | PMBUS_HAVE_STATUS_VOUT; - data->vout_min[i] = 0xffff; - } - break; - case ltc3880: - info->read_word_data = ltc3880_read_word_data; - info->pages = 2; - info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN - | PMBUS_HAVE_STATUS_INPUT - | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT - | PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP - | PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; - info->func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT - | PMBUS_HAVE_POUT - | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - data->vout_min[1] = 0xffff; - break; - default: - return -ENODEV; - } - - return pmbus_do_probe(client, id, info); -} - -/* This is the driver that will be inserted */ -static struct i2c_driver ltc2978_driver = { - .driver = { - .name = "ltc2978", - }, - .probe = ltc2978_probe, - .remove = pmbus_do_remove, - .id_table = ltc2978_id, -}; - -module_i2c_driver(ltc2978_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/max16064.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/max16064.c deleted file mode 100644 index fa237a3c..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/max16064.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Hardware monitoring driver for Maxim MAX16064 - * - * Copyright (c) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include "pmbus.h" - -#define MAX16064_MFR_VOUT_PEAK 0xd4 -#define MAX16064_MFR_TEMPERATURE_PEAK 0xd6 - -static int max16064_read_word_data(struct i2c_client *client, int page, int reg) -{ - int ret; - - switch (reg) { - case PMBUS_VIRT_READ_VOUT_MAX: - ret = pmbus_read_word_data(client, page, - MAX16064_MFR_VOUT_PEAK); - break; - case PMBUS_VIRT_READ_TEMP_MAX: - ret = pmbus_read_word_data(client, page, - MAX16064_MFR_TEMPERATURE_PEAK); - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = 0; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int max16064_write_word_data(struct i2c_client *client, int page, - int reg, u16 word) -{ - int ret; - - switch (reg) { - case PMBUS_VIRT_RESET_VOUT_HISTORY: - ret = pmbus_write_word_data(client, page, - MAX16064_MFR_VOUT_PEAK, 0); - break; - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = pmbus_write_word_data(client, page, - MAX16064_MFR_TEMPERATURE_PEAK, - 0xffff); - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static struct pmbus_driver_info max16064_info = { - .pages = 4, - .format[PSC_VOLTAGE_IN] = direct, - .format[PSC_VOLTAGE_OUT] = direct, - .format[PSC_TEMPERATURE] = direct, - .m[PSC_VOLTAGE_IN] = 19995, - .b[PSC_VOLTAGE_IN] = 0, - .R[PSC_VOLTAGE_IN] = -1, - .m[PSC_VOLTAGE_OUT] = 19995, - .b[PSC_VOLTAGE_OUT] = 0, - .R[PSC_VOLTAGE_OUT] = -1, - .m[PSC_TEMPERATURE] = -7612, - .b[PSC_TEMPERATURE] = 335, - .R[PSC_TEMPERATURE] = -3, - .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP - | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP, - .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, - .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, - .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT, - .read_word_data = max16064_read_word_data, - .write_word_data = max16064_write_word_data, -}; - -static int max16064_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return pmbus_do_probe(client, id, &max16064_info); -} - -static const struct i2c_device_id max16064_id[] = { - {"max16064", 0}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, max16064_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver max16064_driver = { - .driver = { - .name = "max16064", - }, - .probe = max16064_probe, - .remove = pmbus_do_remove, - .id_table = max16064_id, -}; - -module_i2c_driver(max16064_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/max34440.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/max34440.c deleted file mode 100644 index 2ada7b02..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/max34440.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * Hardware monitoring driver for Maxim MAX34440/MAX34441 - * - * Copyright (c) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include "pmbus.h" - -enum chips { max34440, max34441, max34446 }; - -#define MAX34440_MFR_VOUT_PEAK 0xd4 -#define MAX34440_MFR_IOUT_PEAK 0xd5 -#define MAX34440_MFR_TEMPERATURE_PEAK 0xd6 -#define MAX34440_MFR_VOUT_MIN 0xd7 - -#define MAX34446_MFR_POUT_PEAK 0xe0 -#define MAX34446_MFR_POUT_AVG 0xe1 -#define MAX34446_MFR_IOUT_AVG 0xe2 -#define MAX34446_MFR_TEMPERATURE_AVG 0xe3 - -#define MAX34440_STATUS_OC_WARN (1 << 0) -#define MAX34440_STATUS_OC_FAULT (1 << 1) -#define MAX34440_STATUS_OT_FAULT (1 << 5) -#define MAX34440_STATUS_OT_WARN (1 << 6) - -struct max34440_data { - int id; - struct pmbus_driver_info info; -}; - -#define to_max34440_data(x) container_of(x, struct max34440_data, info) - -static int max34440_read_word_data(struct i2c_client *client, int page, int reg) -{ - int ret; - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - const struct max34440_data *data = to_max34440_data(info); - - switch (reg) { - case PMBUS_VIRT_READ_VOUT_MIN: - ret = pmbus_read_word_data(client, page, - MAX34440_MFR_VOUT_MIN); - break; - case PMBUS_VIRT_READ_VOUT_MAX: - ret = pmbus_read_word_data(client, page, - MAX34440_MFR_VOUT_PEAK); - break; - case PMBUS_VIRT_READ_IOUT_AVG: - if (data->id != max34446) - return -ENXIO; - ret = pmbus_read_word_data(client, page, - MAX34446_MFR_IOUT_AVG); - break; - case PMBUS_VIRT_READ_IOUT_MAX: - ret = pmbus_read_word_data(client, page, - MAX34440_MFR_IOUT_PEAK); - break; - case PMBUS_VIRT_READ_POUT_AVG: - if (data->id != max34446) - return -ENXIO; - ret = pmbus_read_word_data(client, page, - MAX34446_MFR_POUT_AVG); - break; - case PMBUS_VIRT_READ_POUT_MAX: - if (data->id != max34446) - return -ENXIO; - ret = pmbus_read_word_data(client, page, - MAX34446_MFR_POUT_PEAK); - break; - case PMBUS_VIRT_READ_TEMP_AVG: - if (data->id != max34446) - return -ENXIO; - ret = pmbus_read_word_data(client, page, - MAX34446_MFR_TEMPERATURE_AVG); - break; - case PMBUS_VIRT_READ_TEMP_MAX: - ret = pmbus_read_word_data(client, page, - MAX34440_MFR_TEMPERATURE_PEAK); - break; - case PMBUS_VIRT_RESET_POUT_HISTORY: - if (data->id != max34446) - return -ENXIO; - ret = 0; - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - case PMBUS_VIRT_RESET_IOUT_HISTORY: - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = 0; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int max34440_write_word_data(struct i2c_client *client, int page, - int reg, u16 word) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - const struct max34440_data *data = to_max34440_data(info); - int ret; - - switch (reg) { - case PMBUS_VIRT_RESET_POUT_HISTORY: - ret = pmbus_write_word_data(client, page, - MAX34446_MFR_POUT_PEAK, 0); - if (ret) - break; - ret = pmbus_write_word_data(client, page, - MAX34446_MFR_POUT_AVG, 0); - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - ret = pmbus_write_word_data(client, page, - MAX34440_MFR_VOUT_MIN, 0x7fff); - if (ret) - break; - ret = pmbus_write_word_data(client, page, - MAX34440_MFR_VOUT_PEAK, 0); - break; - case PMBUS_VIRT_RESET_IOUT_HISTORY: - ret = pmbus_write_word_data(client, page, - MAX34440_MFR_IOUT_PEAK, 0); - if (!ret && data->id == max34446) - ret = pmbus_write_word_data(client, page, - MAX34446_MFR_IOUT_AVG, 0); - - break; - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = pmbus_write_word_data(client, page, - MAX34440_MFR_TEMPERATURE_PEAK, - 0x8000); - if (!ret && data->id == max34446) - ret = pmbus_write_word_data(client, page, - MAX34446_MFR_TEMPERATURE_AVG, 0); - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int max34440_read_byte_data(struct i2c_client *client, int page, int reg) -{ - int ret = 0; - int mfg_status; - - if (page >= 0) { - ret = pmbus_set_page(client, page); - if (ret < 0) - return ret; - } - - switch (reg) { - case PMBUS_STATUS_IOUT: - mfg_status = pmbus_read_word_data(client, 0, - PMBUS_STATUS_MFR_SPECIFIC); - if (mfg_status < 0) - return mfg_status; - if (mfg_status & MAX34440_STATUS_OC_WARN) - ret |= PB_IOUT_OC_WARNING; - if (mfg_status & MAX34440_STATUS_OC_FAULT) - ret |= PB_IOUT_OC_FAULT; - break; - case PMBUS_STATUS_TEMPERATURE: - mfg_status = pmbus_read_word_data(client, 0, - PMBUS_STATUS_MFR_SPECIFIC); - if (mfg_status < 0) - return mfg_status; - if (mfg_status & MAX34440_STATUS_OT_WARN) - ret |= PB_TEMP_OT_WARNING; - if (mfg_status & MAX34440_STATUS_OT_FAULT) - ret |= PB_TEMP_OT_FAULT; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static struct pmbus_driver_info max34440_info[] = { - [max34440] = { - .pages = 14, - .format[PSC_VOLTAGE_IN] = direct, - .format[PSC_VOLTAGE_OUT] = direct, - .format[PSC_TEMPERATURE] = direct, - .format[PSC_CURRENT_OUT] = direct, - .m[PSC_VOLTAGE_IN] = 1, - .b[PSC_VOLTAGE_IN] = 0, - .R[PSC_VOLTAGE_IN] = 3, /* R = 0 in datasheet reflects mV */ - .m[PSC_VOLTAGE_OUT] = 1, - .b[PSC_VOLTAGE_OUT] = 0, - .R[PSC_VOLTAGE_OUT] = 3, /* R = 0 in datasheet reflects mV */ - .m[PSC_CURRENT_OUT] = 1, - .b[PSC_CURRENT_OUT] = 0, - .R[PSC_CURRENT_OUT] = 3, /* R = 0 in datasheet reflects mA */ - .m[PSC_TEMPERATURE] = 1, - .b[PSC_TEMPERATURE] = 0, - .R[PSC_TEMPERATURE] = 2, - .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .read_byte_data = max34440_read_byte_data, - .read_word_data = max34440_read_word_data, - .write_word_data = max34440_write_word_data, - }, - [max34441] = { - .pages = 12, - .format[PSC_VOLTAGE_IN] = direct, - .format[PSC_VOLTAGE_OUT] = direct, - .format[PSC_TEMPERATURE] = direct, - .format[PSC_CURRENT_OUT] = direct, - .format[PSC_FAN] = direct, - .m[PSC_VOLTAGE_IN] = 1, - .b[PSC_VOLTAGE_IN] = 0, - .R[PSC_VOLTAGE_IN] = 3, - .m[PSC_VOLTAGE_OUT] = 1, - .b[PSC_VOLTAGE_OUT] = 0, - .R[PSC_VOLTAGE_OUT] = 3, - .m[PSC_CURRENT_OUT] = 1, - .b[PSC_CURRENT_OUT] = 0, - .R[PSC_CURRENT_OUT] = 3, - .m[PSC_TEMPERATURE] = 1, - .b[PSC_TEMPERATURE] = 0, - .R[PSC_TEMPERATURE] = 2, - .m[PSC_FAN] = 1, - .b[PSC_FAN] = 0, - .R[PSC_FAN] = 0, - .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12, - .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .read_byte_data = max34440_read_byte_data, - .read_word_data = max34440_read_word_data, - .write_word_data = max34440_write_word_data, - }, - [max34446] = { - .pages = 7, - .format[PSC_VOLTAGE_IN] = direct, - .format[PSC_VOLTAGE_OUT] = direct, - .format[PSC_TEMPERATURE] = direct, - .format[PSC_CURRENT_OUT] = direct, - .format[PSC_POWER] = direct, - .m[PSC_VOLTAGE_IN] = 1, - .b[PSC_VOLTAGE_IN] = 0, - .R[PSC_VOLTAGE_IN] = 3, - .m[PSC_VOLTAGE_OUT] = 1, - .b[PSC_VOLTAGE_OUT] = 0, - .R[PSC_VOLTAGE_OUT] = 3, - .m[PSC_CURRENT_OUT] = 1, - .b[PSC_CURRENT_OUT] = 0, - .R[PSC_CURRENT_OUT] = 3, - .m[PSC_POWER] = 1, - .b[PSC_POWER] = 0, - .R[PSC_POWER] = 3, - .m[PSC_TEMPERATURE] = 1, - .b[PSC_TEMPERATURE] = 0, - .R[PSC_TEMPERATURE] = 2, - .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, - .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | PMBUS_HAVE_POUT, - .func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, - .func[4] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[5] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP, - .read_byte_data = max34440_read_byte_data, - .read_word_data = max34440_read_word_data, - .write_word_data = max34440_write_word_data, - }, -}; - -static int max34440_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct max34440_data *data; - - data = devm_kzalloc(&client->dev, sizeof(struct max34440_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - data->id = id->driver_data; - data->info = max34440_info[id->driver_data]; - - return pmbus_do_probe(client, id, &data->info); -} - -static const struct i2c_device_id max34440_id[] = { - {"max34440", max34440}, - {"max34441", max34441}, - {"max34446", max34446}, - {} -}; -MODULE_DEVICE_TABLE(i2c, max34440_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver max34440_driver = { - .driver = { - .name = "max34440", - }, - .probe = max34440_probe, - .remove = pmbus_do_remove, - .id_table = max34440_id, -}; - -module_i2c_driver(max34440_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/max8688.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/max8688.c deleted file mode 100644 index f04454a4..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/max8688.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Hardware monitoring driver for Maxim MAX8688 - * - * Copyright (c) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include "pmbus.h" - -#define MAX8688_MFR_VOUT_PEAK 0xd4 -#define MAX8688_MFR_IOUT_PEAK 0xd5 -#define MAX8688_MFR_TEMPERATURE_PEAK 0xd6 -#define MAX8688_MFG_STATUS 0xd8 - -#define MAX8688_STATUS_OC_FAULT (1 << 4) -#define MAX8688_STATUS_OV_FAULT (1 << 5) -#define MAX8688_STATUS_OV_WARNING (1 << 8) -#define MAX8688_STATUS_UV_FAULT (1 << 9) -#define MAX8688_STATUS_UV_WARNING (1 << 10) -#define MAX8688_STATUS_UC_FAULT (1 << 11) -#define MAX8688_STATUS_OC_WARNING (1 << 12) -#define MAX8688_STATUS_OT_FAULT (1 << 13) -#define MAX8688_STATUS_OT_WARNING (1 << 14) - -static int max8688_read_word_data(struct i2c_client *client, int page, int reg) -{ - int ret; - - if (page) - return -ENXIO; - - switch (reg) { - case PMBUS_VIRT_READ_VOUT_MAX: - ret = pmbus_read_word_data(client, 0, MAX8688_MFR_VOUT_PEAK); - break; - case PMBUS_VIRT_READ_IOUT_MAX: - ret = pmbus_read_word_data(client, 0, MAX8688_MFR_IOUT_PEAK); - break; - case PMBUS_VIRT_READ_TEMP_MAX: - ret = pmbus_read_word_data(client, 0, - MAX8688_MFR_TEMPERATURE_PEAK); - break; - case PMBUS_VIRT_RESET_VOUT_HISTORY: - case PMBUS_VIRT_RESET_IOUT_HISTORY: - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = 0; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int max8688_write_word_data(struct i2c_client *client, int page, int reg, - u16 word) -{ - int ret; - - switch (reg) { - case PMBUS_VIRT_RESET_VOUT_HISTORY: - ret = pmbus_write_word_data(client, 0, MAX8688_MFR_VOUT_PEAK, - 0); - break; - case PMBUS_VIRT_RESET_IOUT_HISTORY: - ret = pmbus_write_word_data(client, 0, MAX8688_MFR_IOUT_PEAK, - 0); - break; - case PMBUS_VIRT_RESET_TEMP_HISTORY: - ret = pmbus_write_word_data(client, 0, - MAX8688_MFR_TEMPERATURE_PEAK, - 0xffff); - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static int max8688_read_byte_data(struct i2c_client *client, int page, int reg) -{ - int ret = 0; - int mfg_status; - - if (page > 0) - return -ENXIO; - - switch (reg) { - case PMBUS_STATUS_VOUT: - mfg_status = pmbus_read_word_data(client, 0, - MAX8688_MFG_STATUS); - if (mfg_status < 0) - return mfg_status; - if (mfg_status & MAX8688_STATUS_UV_WARNING) - ret |= PB_VOLTAGE_UV_WARNING; - if (mfg_status & MAX8688_STATUS_UV_FAULT) - ret |= PB_VOLTAGE_UV_FAULT; - if (mfg_status & MAX8688_STATUS_OV_WARNING) - ret |= PB_VOLTAGE_OV_WARNING; - if (mfg_status & MAX8688_STATUS_OV_FAULT) - ret |= PB_VOLTAGE_OV_FAULT; - break; - case PMBUS_STATUS_IOUT: - mfg_status = pmbus_read_word_data(client, 0, - MAX8688_MFG_STATUS); - if (mfg_status < 0) - return mfg_status; - if (mfg_status & MAX8688_STATUS_UC_FAULT) - ret |= PB_IOUT_UC_FAULT; - if (mfg_status & MAX8688_STATUS_OC_WARNING) - ret |= PB_IOUT_OC_WARNING; - if (mfg_status & MAX8688_STATUS_OC_FAULT) - ret |= PB_IOUT_OC_FAULT; - break; - case PMBUS_STATUS_TEMPERATURE: - mfg_status = pmbus_read_word_data(client, 0, - MAX8688_MFG_STATUS); - if (mfg_status < 0) - return mfg_status; - if (mfg_status & MAX8688_STATUS_OT_WARNING) - ret |= PB_TEMP_OT_WARNING; - if (mfg_status & MAX8688_STATUS_OT_FAULT) - ret |= PB_TEMP_OT_FAULT; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static struct pmbus_driver_info max8688_info = { - .pages = 1, - .format[PSC_VOLTAGE_IN] = direct, - .format[PSC_VOLTAGE_OUT] = direct, - .format[PSC_TEMPERATURE] = direct, - .format[PSC_CURRENT_OUT] = direct, - .m[PSC_VOLTAGE_IN] = 19995, - .b[PSC_VOLTAGE_IN] = 0, - .R[PSC_VOLTAGE_IN] = -1, - .m[PSC_VOLTAGE_OUT] = 19995, - .b[PSC_VOLTAGE_OUT] = 0, - .R[PSC_VOLTAGE_OUT] = -1, - .m[PSC_CURRENT_OUT] = 23109, - .b[PSC_CURRENT_OUT] = 0, - .R[PSC_CURRENT_OUT] = -2, - .m[PSC_TEMPERATURE] = -7612, - .b[PSC_TEMPERATURE] = 335, - .R[PSC_TEMPERATURE] = -3, - .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP - | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT - | PMBUS_HAVE_STATUS_TEMP, - .read_byte_data = max8688_read_byte_data, - .read_word_data = max8688_read_word_data, - .write_word_data = max8688_write_word_data, -}; - -static int max8688_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - return pmbus_do_probe(client, id, &max8688_info); -} - -static const struct i2c_device_id max8688_id[] = { - {"max8688", 0}, - { } -}; - -MODULE_DEVICE_TABLE(i2c, max8688_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver max8688_driver = { - .driver = { - .name = "max8688", - }, - .probe = max8688_probe, - .remove = pmbus_do_remove, - .id_table = max8688_id, -}; - -module_i2c_driver(max8688_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.c deleted file mode 100644 index 7e917001..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.c +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Hardware monitoring driver for PMBus devices - * - * Copyright (c) 2010, 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -/* - * Find sensor groups and status registers on each page. - */ -static void pmbus_find_sensor_groups(struct i2c_client *client, - struct pmbus_driver_info *info) -{ - int page; - - /* Sensors detected on page 0 only */ - if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN)) - info->func[0] |= PMBUS_HAVE_VIN; - if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP)) - info->func[0] |= PMBUS_HAVE_VCAP; - if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN)) - info->func[0] |= PMBUS_HAVE_IIN; - if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN)) - info->func[0] |= PMBUS_HAVE_PIN; - if (info->func[0] - && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT)) - info->func[0] |= PMBUS_HAVE_STATUS_INPUT; - if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_12) && - pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) { - info->func[0] |= PMBUS_HAVE_FAN12; - if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12)) - info->func[0] |= PMBUS_HAVE_STATUS_FAN12; - } - if (pmbus_check_byte_register(client, 0, PMBUS_FAN_CONFIG_34) && - pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) { - info->func[0] |= PMBUS_HAVE_FAN34; - if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34)) - info->func[0] |= PMBUS_HAVE_STATUS_FAN34; - } - if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) - info->func[0] |= PMBUS_HAVE_TEMP; - if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_2)) - info->func[0] |= PMBUS_HAVE_TEMP2; - if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_3)) - info->func[0] |= PMBUS_HAVE_TEMP3; - if (info->func[0] & (PMBUS_HAVE_TEMP | PMBUS_HAVE_TEMP2 - | PMBUS_HAVE_TEMP3) - && pmbus_check_byte_register(client, 0, - PMBUS_STATUS_TEMPERATURE)) - info->func[0] |= PMBUS_HAVE_STATUS_TEMP; - - /* Sensors detected on all pages */ - for (page = 0; page < info->pages; page++) { - if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) { - info->func[page] |= PMBUS_HAVE_VOUT; - if (pmbus_check_byte_register(client, page, - PMBUS_STATUS_VOUT)) - info->func[page] |= PMBUS_HAVE_STATUS_VOUT; - } - if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) { - info->func[page] |= PMBUS_HAVE_IOUT; - if (pmbus_check_byte_register(client, 0, - PMBUS_STATUS_IOUT)) - info->func[page] |= PMBUS_HAVE_STATUS_IOUT; - } - if (pmbus_check_word_register(client, page, PMBUS_READ_POUT)) - info->func[page] |= PMBUS_HAVE_POUT; - } -} - -/* - * Identify chip parameters. - */ -static int pmbus_identify(struct i2c_client *client, - struct pmbus_driver_info *info) -{ - int ret = 0; - - if (!info->pages) { - /* - * Check if the PAGE command is supported. If it is, - * keep setting the page number until it fails or until the - * maximum number of pages has been reached. Assume that - * this is the number of pages supported by the chip. - */ - if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) { - int page; - - for (page = 1; page < PMBUS_PAGES; page++) { - if (pmbus_set_page(client, page) < 0) - break; - } - pmbus_set_page(client, 0); - info->pages = page; - } else { - info->pages = 1; - } - } - - if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) { - int vout_mode; - - vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); - if (vout_mode >= 0 && vout_mode != 0xff) { - switch (vout_mode >> 5) { - case 0: - break; - case 1: - info->format[PSC_VOLTAGE_OUT] = vid; - break; - case 2: - info->format[PSC_VOLTAGE_OUT] = direct; - break; - default: - ret = -ENODEV; - goto abort; - } - } - } - - /* - * We should check if the COEFFICIENTS register is supported. - * If it is, and the chip is configured for direct mode, we can read - * the coefficients from the chip, one set per group of sensor - * registers. - * - * To do this, we will need access to a chip which actually supports the - * COEFFICIENTS command, since the command is too complex to implement - * without testing it. Until then, abort if a chip configured for direct - * mode was detected. - */ - if (info->format[PSC_VOLTAGE_OUT] == direct) { - ret = -ENODEV; - goto abort; - } - - /* Try to find sensor groups */ - pmbus_find_sensor_groups(client, info); -abort: - return ret; -} - -static int pmbus_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct pmbus_driver_info *info; - - info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), - GFP_KERNEL); - if (!info) - return -ENOMEM; - - info->pages = id->driver_data; - info->identify = pmbus_identify; - - return pmbus_do_probe(client, id, info); -} - -/* - * Use driver_data to set the number of pages supported by the chip. - */ -static const struct i2c_device_id pmbus_id[] = { - {"adp4000", 1}, - {"bmr453", 1}, - {"bmr454", 1}, - {"mdt040", 1}, - {"ncp4200", 1}, - {"ncp4208", 1}, - {"pdt003", 1}, - {"pdt006", 1}, - {"pdt012", 1}, - {"pmbus", 0}, - {"tps40400", 1}, - {"tps40422", 2}, - {"udt020", 1}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, pmbus_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver pmbus_driver = { - .driver = { - .name = "pmbus", - }, - .probe = pmbus_probe, - .remove = pmbus_do_remove, - .id_table = pmbus_id, -}; - -module_i2c_driver(pmbus_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("Generic PMBus driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.h b/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.h deleted file mode 100644 index 3fe03dc4..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus.h +++ /dev/null @@ -1,376 +0,0 @@ -/* - * pmbus.h - Common defines and structures for PMBus devices - * - * Copyright (c) 2010, 2011 Ericsson AB. - * - * 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. - */ - -#ifndef PMBUS_H -#define PMBUS_H - -/* - * Registers - */ -#define PMBUS_PAGE 0x00 -#define PMBUS_OPERATION 0x01 -#define PMBUS_ON_OFF_CONFIG 0x02 -#define PMBUS_CLEAR_FAULTS 0x03 -#define PMBUS_PHASE 0x04 - -#define PMBUS_CAPABILITY 0x19 -#define PMBUS_QUERY 0x1A - -#define PMBUS_VOUT_MODE 0x20 -#define PMBUS_VOUT_COMMAND 0x21 -#define PMBUS_VOUT_TRIM 0x22 -#define PMBUS_VOUT_CAL_OFFSET 0x23 -#define PMBUS_VOUT_MAX 0x24 -#define PMBUS_VOUT_MARGIN_HIGH 0x25 -#define PMBUS_VOUT_MARGIN_LOW 0x26 -#define PMBUS_VOUT_TRANSITION_RATE 0x27 -#define PMBUS_VOUT_DROOP 0x28 -#define PMBUS_VOUT_SCALE_LOOP 0x29 -#define PMBUS_VOUT_SCALE_MONITOR 0x2A - -#define PMBUS_COEFFICIENTS 0x30 -#define PMBUS_POUT_MAX 0x31 - -#define PMBUS_FAN_CONFIG_12 0x3A -#define PMBUS_FAN_COMMAND_1 0x3B -#define PMBUS_FAN_COMMAND_2 0x3C -#define PMBUS_FAN_CONFIG_34 0x3D -#define PMBUS_FAN_COMMAND_3 0x3E -#define PMBUS_FAN_COMMAND_4 0x3F - -#define PMBUS_VOUT_OV_FAULT_LIMIT 0x40 -#define PMBUS_VOUT_OV_FAULT_RESPONSE 0x41 -#define PMBUS_VOUT_OV_WARN_LIMIT 0x42 -#define PMBUS_VOUT_UV_WARN_LIMIT 0x43 -#define PMBUS_VOUT_UV_FAULT_LIMIT 0x44 -#define PMBUS_VOUT_UV_FAULT_RESPONSE 0x45 -#define PMBUS_IOUT_OC_FAULT_LIMIT 0x46 -#define PMBUS_IOUT_OC_FAULT_RESPONSE 0x47 -#define PMBUS_IOUT_OC_LV_FAULT_LIMIT 0x48 -#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE 0x49 -#define PMBUS_IOUT_OC_WARN_LIMIT 0x4A -#define PMBUS_IOUT_UC_FAULT_LIMIT 0x4B -#define PMBUS_IOUT_UC_FAULT_RESPONSE 0x4C - -#define PMBUS_OT_FAULT_LIMIT 0x4F -#define PMBUS_OT_FAULT_RESPONSE 0x50 -#define PMBUS_OT_WARN_LIMIT 0x51 -#define PMBUS_UT_WARN_LIMIT 0x52 -#define PMBUS_UT_FAULT_LIMIT 0x53 -#define PMBUS_UT_FAULT_RESPONSE 0x54 -#define PMBUS_VIN_OV_FAULT_LIMIT 0x55 -#define PMBUS_VIN_OV_FAULT_RESPONSE 0x56 -#define PMBUS_VIN_OV_WARN_LIMIT 0x57 -#define PMBUS_VIN_UV_WARN_LIMIT 0x58 -#define PMBUS_VIN_UV_FAULT_LIMIT 0x59 - -#define PMBUS_IIN_OC_FAULT_LIMIT 0x5B -#define PMBUS_IIN_OC_WARN_LIMIT 0x5D - -#define PMBUS_POUT_OP_FAULT_LIMIT 0x68 -#define PMBUS_POUT_OP_WARN_LIMIT 0x6A -#define PMBUS_PIN_OP_WARN_LIMIT 0x6B - -#define PMBUS_STATUS_BYTE 0x78 -#define PMBUS_STATUS_WORD 0x79 -#define PMBUS_STATUS_VOUT 0x7A -#define PMBUS_STATUS_IOUT 0x7B -#define PMBUS_STATUS_INPUT 0x7C -#define PMBUS_STATUS_TEMPERATURE 0x7D -#define PMBUS_STATUS_CML 0x7E -#define PMBUS_STATUS_OTHER 0x7F -#define PMBUS_STATUS_MFR_SPECIFIC 0x80 -#define PMBUS_STATUS_FAN_12 0x81 -#define PMBUS_STATUS_FAN_34 0x82 - -#define PMBUS_READ_VIN 0x88 -#define PMBUS_READ_IIN 0x89 -#define PMBUS_READ_VCAP 0x8A -#define PMBUS_READ_VOUT 0x8B -#define PMBUS_READ_IOUT 0x8C -#define PMBUS_READ_TEMPERATURE_1 0x8D -#define PMBUS_READ_TEMPERATURE_2 0x8E -#define PMBUS_READ_TEMPERATURE_3 0x8F -#define PMBUS_READ_FAN_SPEED_1 0x90 -#define PMBUS_READ_FAN_SPEED_2 0x91 -#define PMBUS_READ_FAN_SPEED_3 0x92 -#define PMBUS_READ_FAN_SPEED_4 0x93 -#define PMBUS_READ_DUTY_CYCLE 0x94 -#define PMBUS_READ_FREQUENCY 0x95 -#define PMBUS_READ_POUT 0x96 -#define PMBUS_READ_PIN 0x97 - -#define PMBUS_REVISION 0x98 -#define PMBUS_MFR_ID 0x99 -#define PMBUS_MFR_MODEL 0x9A -#define PMBUS_MFR_REVISION 0x9B -#define PMBUS_MFR_LOCATION 0x9C -#define PMBUS_MFR_DATE 0x9D -#define PMBUS_MFR_SERIAL 0x9E - -/* - * Virtual registers. - * Useful to support attributes which are not supported by standard PMBus - * registers but exist as manufacturer specific registers on individual chips. - * Must be mapped to real registers in device specific code. - * - * Semantics: - * Virtual registers are all word size. - * READ registers are read-only; writes are either ignored or return an error. - * RESET registers are read/write. Reading reset registers returns zero - * (used for detection), writing any value causes the associated history to be - * reset. - * Virtual registers have to be handled in device specific driver code. Chip - * driver code returns non-negative register values if a virtual register is - * supported, or a negative error code if not. The chip driver may return - * -ENODATA or any other error code in this case, though an error code other - * than -ENODATA is handled more efficiently and thus preferred. Either case, - * the calling PMBus core code will abort if the chip driver returns an error - * code when reading or writing virtual registers. - */ -#define PMBUS_VIRT_BASE 0x100 -#define PMBUS_VIRT_READ_TEMP_AVG (PMBUS_VIRT_BASE + 0) -#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 1) -#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 2) -#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 3) -#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 4) -#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 5) -#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 6) -#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 7) -#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 8) -#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 9) -#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 10) -#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 11) -#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 12) -#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 13) -#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 14) -#define PMBUS_VIRT_READ_POUT_AVG (PMBUS_VIRT_BASE + 15) -#define PMBUS_VIRT_READ_POUT_MAX (PMBUS_VIRT_BASE + 16) -#define PMBUS_VIRT_RESET_POUT_HISTORY (PMBUS_VIRT_BASE + 17) -#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 18) -#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 19) -#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 20) -#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 21) -#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 22) -#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 23) -#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 24) -#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 25) -#define PMBUS_VIRT_READ_TEMP2_AVG (PMBUS_VIRT_BASE + 26) -#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 27) -#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 28) -#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 29) - -/* - * CAPABILITY - */ -#define PB_CAPABILITY_SMBALERT (1<<4) -#define PB_CAPABILITY_ERROR_CHECK (1<<7) - -/* - * VOUT_MODE - */ -#define PB_VOUT_MODE_MODE_MASK 0xe0 -#define PB_VOUT_MODE_PARAM_MASK 0x1f - -#define PB_VOUT_MODE_LINEAR 0x00 -#define PB_VOUT_MODE_VID 0x20 -#define PB_VOUT_MODE_DIRECT 0x40 - -/* - * Fan configuration - */ -#define PB_FAN_2_PULSE_MASK ((1 << 0) | (1 << 1)) -#define PB_FAN_2_RPM (1 << 2) -#define PB_FAN_2_INSTALLED (1 << 3) -#define PB_FAN_1_PULSE_MASK ((1 << 4) | (1 << 5)) -#define PB_FAN_1_RPM (1 << 6) -#define PB_FAN_1_INSTALLED (1 << 7) - -/* - * STATUS_BYTE, STATUS_WORD (lower) - */ -#define PB_STATUS_NONE_ABOVE (1<<0) -#define PB_STATUS_CML (1<<1) -#define PB_STATUS_TEMPERATURE (1<<2) -#define PB_STATUS_VIN_UV (1<<3) -#define PB_STATUS_IOUT_OC (1<<4) -#define PB_STATUS_VOUT_OV (1<<5) -#define PB_STATUS_OFF (1<<6) -#define PB_STATUS_BUSY (1<<7) - -/* - * STATUS_WORD (upper) - */ -#define PB_STATUS_UNKNOWN (1<<8) -#define PB_STATUS_OTHER (1<<9) -#define PB_STATUS_FANS (1<<10) -#define PB_STATUS_POWER_GOOD_N (1<<11) -#define PB_STATUS_WORD_MFR (1<<12) -#define PB_STATUS_INPUT (1<<13) -#define PB_STATUS_IOUT_POUT (1<<14) -#define PB_STATUS_VOUT (1<<15) - -/* - * STATUS_IOUT - */ -#define PB_POUT_OP_WARNING (1<<0) -#define PB_POUT_OP_FAULT (1<<1) -#define PB_POWER_LIMITING (1<<2) -#define PB_CURRENT_SHARE_FAULT (1<<3) -#define PB_IOUT_UC_FAULT (1<<4) -#define PB_IOUT_OC_WARNING (1<<5) -#define PB_IOUT_OC_LV_FAULT (1<<6) -#define PB_IOUT_OC_FAULT (1<<7) - -/* - * STATUS_VOUT, STATUS_INPUT - */ -#define PB_VOLTAGE_UV_FAULT (1<<4) -#define PB_VOLTAGE_UV_WARNING (1<<5) -#define PB_VOLTAGE_OV_WARNING (1<<6) -#define PB_VOLTAGE_OV_FAULT (1<<7) - -/* - * STATUS_INPUT - */ -#define PB_PIN_OP_WARNING (1<<0) -#define PB_IIN_OC_WARNING (1<<1) -#define PB_IIN_OC_FAULT (1<<2) - -/* - * STATUS_TEMPERATURE - */ -#define PB_TEMP_UT_FAULT (1<<4) -#define PB_TEMP_UT_WARNING (1<<5) -#define PB_TEMP_OT_WARNING (1<<6) -#define PB_TEMP_OT_FAULT (1<<7) - -/* - * STATUS_FAN - */ -#define PB_FAN_AIRFLOW_WARNING (1<<0) -#define PB_FAN_AIRFLOW_FAULT (1<<1) -#define PB_FAN_FAN2_SPEED_OVERRIDE (1<<2) -#define PB_FAN_FAN1_SPEED_OVERRIDE (1<<3) -#define PB_FAN_FAN2_WARNING (1<<4) -#define PB_FAN_FAN1_WARNING (1<<5) -#define PB_FAN_FAN2_FAULT (1<<6) -#define PB_FAN_FAN1_FAULT (1<<7) - -/* - * CML_FAULT_STATUS - */ -#define PB_CML_FAULT_OTHER_MEM_LOGIC (1<<0) -#define PB_CML_FAULT_OTHER_COMM (1<<1) -#define PB_CML_FAULT_PROCESSOR (1<<3) -#define PB_CML_FAULT_MEMORY (1<<4) -#define PB_CML_FAULT_PACKET_ERROR (1<<5) -#define PB_CML_FAULT_INVALID_DATA (1<<6) -#define PB_CML_FAULT_INVALID_COMMAND (1<<7) - -enum pmbus_sensor_classes { - PSC_VOLTAGE_IN = 0, - PSC_VOLTAGE_OUT, - PSC_CURRENT_IN, - PSC_CURRENT_OUT, - PSC_POWER, - PSC_TEMPERATURE, - PSC_FAN, - PSC_NUM_CLASSES /* Number of power sensor classes */ -}; - -#define PMBUS_PAGES 32 /* Per PMBus specification */ - -/* Functionality bit mask */ -#define PMBUS_HAVE_VIN (1 << 0) -#define PMBUS_HAVE_VCAP (1 << 1) -#define PMBUS_HAVE_VOUT (1 << 2) -#define PMBUS_HAVE_IIN (1 << 3) -#define PMBUS_HAVE_IOUT (1 << 4) -#define PMBUS_HAVE_PIN (1 << 5) -#define PMBUS_HAVE_POUT (1 << 6) -#define PMBUS_HAVE_FAN12 (1 << 7) -#define PMBUS_HAVE_FAN34 (1 << 8) -#define PMBUS_HAVE_TEMP (1 << 9) -#define PMBUS_HAVE_TEMP2 (1 << 10) -#define PMBUS_HAVE_TEMP3 (1 << 11) -#define PMBUS_HAVE_STATUS_VOUT (1 << 12) -#define PMBUS_HAVE_STATUS_IOUT (1 << 13) -#define PMBUS_HAVE_STATUS_INPUT (1 << 14) -#define PMBUS_HAVE_STATUS_TEMP (1 << 15) -#define PMBUS_HAVE_STATUS_FAN12 (1 << 16) -#define PMBUS_HAVE_STATUS_FAN34 (1 << 17) - -enum pmbus_data_format { linear = 0, direct, vid }; - -struct pmbus_driver_info { - int pages; /* Total number of pages */ - enum pmbus_data_format format[PSC_NUM_CLASSES]; - /* - * Support one set of coefficients for each sensor type - * Used for chips providing data in direct mode. - */ - int m[PSC_NUM_CLASSES]; /* mantissa for direct data format */ - int b[PSC_NUM_CLASSES]; /* offset */ - int R[PSC_NUM_CLASSES]; /* exponent */ - - u32 func[PMBUS_PAGES]; /* Functionality, per page */ - /* - * The following functions map manufacturing specific register values - * to PMBus standard register values. Specify only if mapping is - * necessary. - * Functions return the register value (read) or zero (write) if - * successful. A return value of -ENODATA indicates that there is no - * manufacturer specific register, but that a standard PMBus register - * may exist. Any other negative return value indicates that the - * register does not exist, and that no attempt should be made to read - * the standard register. - */ - int (*read_byte_data)(struct i2c_client *client, int page, int reg); - int (*read_word_data)(struct i2c_client *client, int page, int reg); - int (*write_word_data)(struct i2c_client *client, int page, int reg, - u16 word); - int (*write_byte)(struct i2c_client *client, int page, u8 value); - /* - * The identify function determines supported PMBus functionality. - * This function is only necessary if a chip driver supports multiple - * chips, and the chip functionality is not pre-determined. - */ - int (*identify)(struct i2c_client *client, - struct pmbus_driver_info *info); -}; - -/* Function declarations */ - -int pmbus_set_page(struct i2c_client *client, u8 page); -int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); -int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); -int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); -int pmbus_write_byte(struct i2c_client *client, int page, u8 value); -void pmbus_clear_faults(struct i2c_client *client); -bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); -bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); -int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, - struct pmbus_driver_info *info); -int pmbus_do_remove(struct i2c_client *client); -const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client - *client); - -#endif /* PMBUS_H */ diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus_core.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus_core.c deleted file mode 100644 index 29b319db..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/pmbus_core.c +++ /dev/null @@ -1,1811 +0,0 @@ -/* - * Hardware monitoring driver for PMBus devices - * - * Copyright (c) 2010, 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -/* - * Constants needed to determine number of sensors, booleans, and labels. - */ -#define PMBUS_MAX_INPUT_SENSORS 22 /* 10*volt, 7*curr, 5*power */ -#define PMBUS_VOUT_SENSORS_PER_PAGE 9 /* input, min, max, lcrit, - crit, lowest, highest, avg, - reset */ -#define PMBUS_IOUT_SENSORS_PER_PAGE 8 /* input, min, max, crit, - lowest, highest, avg, - reset */ -#define PMBUS_POUT_SENSORS_PER_PAGE 7 /* input, cap, max, crit, - * highest, avg, reset - */ -#define PMBUS_MAX_SENSORS_PER_FAN 1 /* input */ -#define PMBUS_MAX_SENSORS_PER_TEMP 9 /* input, min, max, lcrit, - * crit, lowest, highest, avg, - * reset - */ - -#define PMBUS_MAX_INPUT_BOOLEANS 7 /* v: min_alarm, max_alarm, - lcrit_alarm, crit_alarm; - c: alarm, crit_alarm; - p: crit_alarm */ -#define PMBUS_VOUT_BOOLEANS_PER_PAGE 4 /* min_alarm, max_alarm, - lcrit_alarm, crit_alarm */ -#define PMBUS_IOUT_BOOLEANS_PER_PAGE 3 /* alarm, lcrit_alarm, - crit_alarm */ -#define PMBUS_POUT_BOOLEANS_PER_PAGE 3 /* cap_alarm, alarm, crit_alarm - */ -#define PMBUS_MAX_BOOLEANS_PER_FAN 2 /* alarm, fault */ -#define PMBUS_MAX_BOOLEANS_PER_TEMP 4 /* min_alarm, max_alarm, - lcrit_alarm, crit_alarm */ - -#define PMBUS_MAX_INPUT_LABELS 4 /* vin, vcap, iin, pin */ - -/* - * status, status_vout, status_iout, status_fans, status_fan34, and status_temp - * are paged. status_input is unpaged. - */ -#define PB_NUM_STATUS_REG (PMBUS_PAGES * 6 + 1) - -/* - * Index into status register array, per status register group - */ -#define PB_STATUS_BASE 0 -#define PB_STATUS_VOUT_BASE (PB_STATUS_BASE + PMBUS_PAGES) -#define PB_STATUS_IOUT_BASE (PB_STATUS_VOUT_BASE + PMBUS_PAGES) -#define PB_STATUS_FAN_BASE (PB_STATUS_IOUT_BASE + PMBUS_PAGES) -#define PB_STATUS_FAN34_BASE (PB_STATUS_FAN_BASE + PMBUS_PAGES) -#define PB_STATUS_INPUT_BASE (PB_STATUS_FAN34_BASE + PMBUS_PAGES) -#define PB_STATUS_TEMP_BASE (PB_STATUS_INPUT_BASE + 1) - -#define PMBUS_NAME_SIZE 24 - -struct pmbus_sensor { - char name[PMBUS_NAME_SIZE]; /* sysfs sensor name */ - struct sensor_device_attribute attribute; - u8 page; /* page number */ - u16 reg; /* register */ - enum pmbus_sensor_classes class; /* sensor class */ - bool update; /* runtime sensor update needed */ - int data; /* Sensor data. - Negative if there was a read error */ -}; - -struct pmbus_boolean { - char name[PMBUS_NAME_SIZE]; /* sysfs boolean name */ - struct sensor_device_attribute attribute; -}; - -struct pmbus_label { - char name[PMBUS_NAME_SIZE]; /* sysfs label name */ - struct sensor_device_attribute attribute; - char label[PMBUS_NAME_SIZE]; /* label */ -}; - -struct pmbus_data { - struct device *hwmon_dev; - - u32 flags; /* from platform data */ - - int exponent; /* linear mode: exponent for output voltages */ - - const struct pmbus_driver_info *info; - - int max_attributes; - int num_attributes; - struct attribute **attributes; - struct attribute_group group; - - /* - * Sensors cover both sensor and limit registers. - */ - int max_sensors; - int num_sensors; - struct pmbus_sensor *sensors; - /* - * Booleans are used for alarms. - * Values are determined from status registers. - */ - int max_booleans; - int num_booleans; - struct pmbus_boolean *booleans; - /* - * Labels are used to map generic names (e.g., "in1") - * to PMBus specific names (e.g., "vin" or "vout1"). - */ - int max_labels; - int num_labels; - struct pmbus_label *labels; - - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - - /* - * A single status register covers multiple attributes, - * so we keep them all together. - */ - u8 status[PB_NUM_STATUS_REG]; - - u8 currpage; -}; - -int pmbus_set_page(struct i2c_client *client, u8 page) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - int rv = 0; - int newpage; - - if (page != data->currpage) { - rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page); - newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE); - if (newpage != page) - rv = -EIO; - else - data->currpage = page; - } - return rv; -} -EXPORT_SYMBOL_GPL(pmbus_set_page); - -int pmbus_write_byte(struct i2c_client *client, int page, u8 value) -{ - int rv; - - if (page >= 0) { - rv = pmbus_set_page(client, page); - if (rv < 0) - return rv; - } - - return i2c_smbus_write_byte(client, value); -} -EXPORT_SYMBOL_GPL(pmbus_write_byte); - -/* - * _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if - * a device specific mapping funcion exists and calls it if necessary. - */ -static int _pmbus_write_byte(struct i2c_client *client, int page, u8 value) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - const struct pmbus_driver_info *info = data->info; - int status; - - if (info->write_byte) { - status = info->write_byte(client, page, value); - if (status != -ENODATA) - return status; - } - return pmbus_write_byte(client, page, value); -} - -int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word) -{ - int rv; - - rv = pmbus_set_page(client, page); - if (rv < 0) - return rv; - - return i2c_smbus_write_word_data(client, reg, word); -} -EXPORT_SYMBOL_GPL(pmbus_write_word_data); - -/* - * _pmbus_write_word_data() is similar to pmbus_write_word_data(), but checks if - * a device specific mapping function exists and calls it if necessary. - */ -static int _pmbus_write_word_data(struct i2c_client *client, int page, int reg, - u16 word) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - const struct pmbus_driver_info *info = data->info; - int status; - - if (info->write_word_data) { - status = info->write_word_data(client, page, reg, word); - if (status != -ENODATA) - return status; - } - if (reg >= PMBUS_VIRT_BASE) - return -ENXIO; - return pmbus_write_word_data(client, page, reg, word); -} - -int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg) -{ - int rv; - - rv = pmbus_set_page(client, page); - if (rv < 0) - return rv; - - return i2c_smbus_read_word_data(client, reg); -} -EXPORT_SYMBOL_GPL(pmbus_read_word_data); - -/* - * _pmbus_read_word_data() is similar to pmbus_read_word_data(), but checks if - * a device specific mapping function exists and calls it if necessary. - */ -static int _pmbus_read_word_data(struct i2c_client *client, int page, int reg) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - const struct pmbus_driver_info *info = data->info; - int status; - - if (info->read_word_data) { - status = info->read_word_data(client, page, reg); - if (status != -ENODATA) - return status; - } - if (reg >= PMBUS_VIRT_BASE) - return -ENXIO; - return pmbus_read_word_data(client, page, reg); -} - -int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg) -{ - int rv; - - if (page >= 0) { - rv = pmbus_set_page(client, page); - if (rv < 0) - return rv; - } - - return i2c_smbus_read_byte_data(client, reg); -} -EXPORT_SYMBOL_GPL(pmbus_read_byte_data); - -/* - * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if - * a device specific mapping function exists and calls it if necessary. - */ -static int _pmbus_read_byte_data(struct i2c_client *client, int page, int reg) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - const struct pmbus_driver_info *info = data->info; - int status; - - if (info->read_byte_data) { - status = info->read_byte_data(client, page, reg); - if (status != -ENODATA) - return status; - } - return pmbus_read_byte_data(client, page, reg); -} - -static void pmbus_clear_fault_page(struct i2c_client *client, int page) -{ - _pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS); -} - -void pmbus_clear_faults(struct i2c_client *client) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - int i; - - for (i = 0; i < data->info->pages; i++) - pmbus_clear_fault_page(client, i); -} -EXPORT_SYMBOL_GPL(pmbus_clear_faults); - -static int pmbus_check_status_cml(struct i2c_client *client) -{ - int status, status2; - - status = _pmbus_read_byte_data(client, -1, PMBUS_STATUS_BYTE); - 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)) - return -EIO; - } - return 0; -} - -bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg) -{ - int rv; - struct pmbus_data *data = i2c_get_clientdata(client); - - rv = _pmbus_read_byte_data(client, page, reg); - if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) - rv = pmbus_check_status_cml(client); - pmbus_clear_fault_page(client, -1); - return rv >= 0; -} -EXPORT_SYMBOL_GPL(pmbus_check_byte_register); - -bool pmbus_check_word_register(struct i2c_client *client, int page, int reg) -{ - int rv; - struct pmbus_data *data = i2c_get_clientdata(client); - - rv = _pmbus_read_word_data(client, page, reg); - if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK)) - rv = pmbus_check_status_cml(client); - pmbus_clear_fault_page(client, -1); - return rv >= 0; -} -EXPORT_SYMBOL_GPL(pmbus_check_word_register); - -const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - - return data->info; -} -EXPORT_SYMBOL_GPL(pmbus_get_driver_info); - -static struct pmbus_data *pmbus_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pmbus_data *data = i2c_get_clientdata(client); - const struct pmbus_driver_info *info = data->info; - - mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int i; - - for (i = 0; i < info->pages; i++) - data->status[PB_STATUS_BASE + i] - = _pmbus_read_byte_data(client, i, - PMBUS_STATUS_BYTE); - for (i = 0; i < info->pages; i++) { - if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT)) - continue; - data->status[PB_STATUS_VOUT_BASE + i] - = _pmbus_read_byte_data(client, i, PMBUS_STATUS_VOUT); - } - for (i = 0; i < info->pages; i++) { - if (!(info->func[i] & PMBUS_HAVE_STATUS_IOUT)) - continue; - data->status[PB_STATUS_IOUT_BASE + i] - = _pmbus_read_byte_data(client, i, PMBUS_STATUS_IOUT); - } - for (i = 0; i < info->pages; i++) { - if (!(info->func[i] & PMBUS_HAVE_STATUS_TEMP)) - continue; - data->status[PB_STATUS_TEMP_BASE + i] - = _pmbus_read_byte_data(client, i, - PMBUS_STATUS_TEMPERATURE); - } - for (i = 0; i < info->pages; i++) { - if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN12)) - continue; - data->status[PB_STATUS_FAN_BASE + i] - = _pmbus_read_byte_data(client, i, - PMBUS_STATUS_FAN_12); - } - - for (i = 0; i < info->pages; i++) { - if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN34)) - continue; - data->status[PB_STATUS_FAN34_BASE + i] - = _pmbus_read_byte_data(client, i, - PMBUS_STATUS_FAN_34); - } - - if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) - data->status[PB_STATUS_INPUT_BASE] - = _pmbus_read_byte_data(client, 0, - PMBUS_STATUS_INPUT); - - for (i = 0; i < data->num_sensors; i++) { - struct pmbus_sensor *sensor = &data->sensors[i]; - - if (!data->valid || sensor->update) - sensor->data - = _pmbus_read_word_data(client, - sensor->page, - sensor->reg); - } - pmbus_clear_faults(client); - data->last_updated = jiffies; - data->valid = 1; - } - mutex_unlock(&data->update_lock); - return data; -} - -/* - * Convert linear sensor values to milli- or micro-units - * depending on sensor type. - */ -static long pmbus_reg2data_linear(struct pmbus_data *data, - struct pmbus_sensor *sensor) -{ - s16 exponent; - s32 mantissa; - long val; - - if (sensor->class == PSC_VOLTAGE_OUT) { /* LINEAR16 */ - exponent = data->exponent; - mantissa = (u16) sensor->data; - } else { /* LINEAR11 */ - exponent = ((s16)sensor->data) >> 11; - mantissa = ((s16)((sensor->data & 0x7ff) << 5)) >> 5; - } - - val = mantissa; - - /* scale result to milli-units for all sensors except fans */ - if (sensor->class != PSC_FAN) - val = val * 1000L; - - /* scale result to micro-units for power sensors */ - if (sensor->class == PSC_POWER) - val = val * 1000L; - - if (exponent >= 0) - val <<= exponent; - else - val >>= -exponent; - - return val; -} - -/* - * Convert direct sensor values to milli- or micro-units - * depending on sensor type. - */ -static long pmbus_reg2data_direct(struct pmbus_data *data, - struct pmbus_sensor *sensor) -{ - long val = (s16) sensor->data; - long m, b, R; - - m = data->info->m[sensor->class]; - b = data->info->b[sensor->class]; - R = data->info->R[sensor->class]; - - if (m == 0) - return 0; - - /* X = 1/m * (Y * 10^-R - b) */ - R = -R; - /* scale result to milli-units for everything but fans */ - if (sensor->class != PSC_FAN) { - R += 3; - b *= 1000; - } - - /* scale result to micro-units for power sensors */ - if (sensor->class == PSC_POWER) { - R += 3; - b *= 1000; - } - - while (R > 0) { - val *= 10; - R--; - } - while (R < 0) { - val = DIV_ROUND_CLOSEST(val, 10); - R++; - } - - return (val - b) / m; -} - -/* - * Convert VID sensor values to milli- or micro-units - * depending on sensor type. - * We currently only support VR11. - */ -static long pmbus_reg2data_vid(struct pmbus_data *data, - struct pmbus_sensor *sensor) -{ - long val = sensor->data; - - if (val < 0x02 || val > 0xb2) - return 0; - return DIV_ROUND_CLOSEST(160000 - (val - 2) * 625, 100); -} - -static long pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor) -{ - long val; - - switch (data->info->format[sensor->class]) { - case direct: - val = pmbus_reg2data_direct(data, sensor); - break; - case vid: - val = pmbus_reg2data_vid(data, sensor); - break; - case linear: - default: - val = pmbus_reg2data_linear(data, sensor); - break; - } - return val; -} - -#define MAX_MANTISSA (1023 * 1000) -#define MIN_MANTISSA (511 * 1000) - -static u16 pmbus_data2reg_linear(struct pmbus_data *data, - enum pmbus_sensor_classes class, long val) -{ - s16 exponent = 0, mantissa; - bool negative = false; - - /* simple case */ - if (val == 0) - return 0; - - if (class == PSC_VOLTAGE_OUT) { - /* LINEAR16 does not support negative voltages */ - if (val < 0) - return 0; - - /* - * For a static exponents, we don't have a choice - * but to adjust the value to it. - */ - if (data->exponent < 0) - val <<= -data->exponent; - else - val >>= data->exponent; - val = DIV_ROUND_CLOSEST(val, 1000); - return val & 0xffff; - } - - if (val < 0) { - negative = true; - val = -val; - } - - /* Power is in uW. Convert to mW before converting. */ - if (class == PSC_POWER) - val = DIV_ROUND_CLOSEST(val, 1000L); - - /* - * For simplicity, convert fan data to milli-units - * before calculating the exponent. - */ - if (class == PSC_FAN) - val = val * 1000; - - /* Reduce large mantissa until it fits into 10 bit */ - while (val >= MAX_MANTISSA && exponent < 15) { - exponent++; - val >>= 1; - } - /* Increase small mantissa to improve precision */ - while (val < MIN_MANTISSA && exponent > -15) { - exponent--; - val <<= 1; - } - - /* Convert mantissa from milli-units to units */ - mantissa = DIV_ROUND_CLOSEST(val, 1000); - - /* Ensure that resulting number is within range */ - if (mantissa > 0x3ff) - mantissa = 0x3ff; - - /* restore sign */ - if (negative) - mantissa = -mantissa; - - /* Convert to 5 bit exponent, 11 bit mantissa */ - return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800); -} - -static u16 pmbus_data2reg_direct(struct pmbus_data *data, - enum pmbus_sensor_classes class, long val) -{ - long m, b, R; - - m = data->info->m[class]; - b = data->info->b[class]; - R = data->info->R[class]; - - /* Power is in uW. Adjust R and b. */ - if (class == PSC_POWER) { - R -= 3; - b *= 1000; - } - - /* Calculate Y = (m * X + b) * 10^R */ - if (class != PSC_FAN) { - R -= 3; /* Adjust R and b for data in milli-units */ - b *= 1000; - } - val = val * m + b; - - while (R > 0) { - val *= 10; - R--; - } - while (R < 0) { - val = DIV_ROUND_CLOSEST(val, 10); - R++; - } - - return val; -} - -static u16 pmbus_data2reg_vid(struct pmbus_data *data, - enum pmbus_sensor_classes class, long val) -{ - val = SENSORS_LIMIT(val, 500, 1600); - - return 2 + DIV_ROUND_CLOSEST((1600 - val) * 100, 625); -} - -static u16 pmbus_data2reg(struct pmbus_data *data, - enum pmbus_sensor_classes class, long val) -{ - u16 regval; - - switch (data->info->format[class]) { - case direct: - regval = pmbus_data2reg_direct(data, class, val); - break; - case vid: - regval = pmbus_data2reg_vid(data, class, val); - break; - case linear: - default: - regval = pmbus_data2reg_linear(data, class, val); - break; - } - return regval; -} - -/* - * Return boolean calculated from converted data. - * defines a status register index and mask, and optionally - * two sensor indexes. - * The upper half-word references the two sensors, - * two sensor indices. - * The upper half-word references the two optional sensors, - * the lower half word references status register and mask. - * The function returns true if (status[reg] & mask) is true and, - * if specified, if v1 >= v2. - * To determine if an object exceeds upper limits, specify . - * To determine if an object exceeds lower limits, specify . - * - * For booleans created with pmbus_add_boolean_reg(), only the lower 16 bits of - * index are set. s1 and s2 (the sensor index values) are zero in this case. - * The function returns true if (status[reg] & mask) is true. - * - * If the boolean was created with pmbus_add_boolean_cmp(), a comparison against - * a specified limit has to be performed to determine the boolean result. - * In this case, the function returns true if v1 >= v2 (where v1 and v2 are - * sensor values referenced by sensor indices s1 and s2). - * - * To determine if an object exceeds upper limits, specify = . - * To determine if an object exceeds lower limits, specify = . - * - * If a negative value is stored in any of the referenced registers, this value - * reflects an error code which will be returned. - */ -static int pmbus_get_boolean(struct pmbus_data *data, int index) -{ - u8 s1 = (index >> 24) & 0xff; - u8 s2 = (index >> 16) & 0xff; - u8 reg = (index >> 8) & 0xff; - u8 mask = index & 0xff; - int ret, status; - u8 regval; - - status = data->status[reg]; - if (status < 0) - return status; - - regval = status & mask; - if (!s1 && !s2) - ret = !!regval; - else { - long v1, v2; - struct pmbus_sensor *sensor1, *sensor2; - - sensor1 = &data->sensors[s1]; - if (sensor1->data < 0) - return sensor1->data; - sensor2 = &data->sensors[s2]; - if (sensor2->data < 0) - return sensor2->data; - - v1 = pmbus_reg2data(data, sensor1); - v2 = pmbus_reg2data(data, sensor2); - ret = !!(regval && v1 >= v2); - } - return ret; -} - -static ssize_t pmbus_show_boolean(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct pmbus_data *data = pmbus_update_device(dev); - int val; - - val = pmbus_get_boolean(data, attr->index); - if (val < 0) - return val; - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t pmbus_show_sensor(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct pmbus_data *data = pmbus_update_device(dev); - struct pmbus_sensor *sensor; - - sensor = &data->sensors[attr->index]; - if (sensor->data < 0) - return sensor->data; - - return snprintf(buf, PAGE_SIZE, "%ld\n", pmbus_reg2data(data, sensor)); -} - -static ssize_t pmbus_set_sensor(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct pmbus_data *data = i2c_get_clientdata(client); - struct pmbus_sensor *sensor = &data->sensors[attr->index]; - ssize_t rv = count; - long val = 0; - int ret; - u16 regval; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - regval = pmbus_data2reg(data, sensor->class, val); - ret = _pmbus_write_word_data(client, sensor->page, sensor->reg, regval); - if (ret < 0) - rv = ret; - else - data->sensors[attr->index].data = regval; - mutex_unlock(&data->update_lock); - return rv; -} - -static ssize_t pmbus_show_label(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct pmbus_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - - return snprintf(buf, PAGE_SIZE, "%s\n", - data->labels[attr->index].label); -} - -#define PMBUS_ADD_ATTR(data, _name, _idx, _mode, _type, _show, _set) \ -do { \ - struct sensor_device_attribute *a \ - = &data->_type##s[data->num_##_type##s].attribute; \ - BUG_ON(data->num_attributes >= data->max_attributes); \ - sysfs_attr_init(&a->dev_attr.attr); \ - a->dev_attr.attr.name = _name; \ - a->dev_attr.attr.mode = _mode; \ - a->dev_attr.show = _show; \ - a->dev_attr.store = _set; \ - a->index = _idx; \ - data->attributes[data->num_attributes] = &a->dev_attr.attr; \ - data->num_attributes++; \ -} while (0) - -#define PMBUS_ADD_GET_ATTR(data, _name, _type, _idx) \ - PMBUS_ADD_ATTR(data, _name, _idx, S_IRUGO, _type, \ - pmbus_show_##_type, NULL) - -#define PMBUS_ADD_SET_ATTR(data, _name, _type, _idx) \ - PMBUS_ADD_ATTR(data, _name, _idx, S_IWUSR | S_IRUGO, _type, \ - pmbus_show_##_type, pmbus_set_##_type) - -static void pmbus_add_boolean(struct pmbus_data *data, - const char *name, const char *type, int seq, - int idx) -{ - struct pmbus_boolean *boolean; - - BUG_ON(data->num_booleans >= data->max_booleans); - - boolean = &data->booleans[data->num_booleans]; - - snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s", - name, seq, type); - PMBUS_ADD_GET_ATTR(data, boolean->name, boolean, idx); - data->num_booleans++; -} - -static void pmbus_add_boolean_reg(struct pmbus_data *data, - const char *name, const char *type, - int seq, int reg, int bit) -{ - pmbus_add_boolean(data, name, type, seq, (reg << 8) | bit); -} - -static void pmbus_add_boolean_cmp(struct pmbus_data *data, - const char *name, const char *type, - int seq, int i1, int i2, int reg, int mask) -{ - pmbus_add_boolean(data, name, type, seq, - (i1 << 24) | (i2 << 16) | (reg << 8) | mask); -} - -static void pmbus_add_sensor(struct pmbus_data *data, - const char *name, const char *type, int seq, - int page, int reg, enum pmbus_sensor_classes class, - bool update, bool readonly) -{ - struct pmbus_sensor *sensor; - - BUG_ON(data->num_sensors >= data->max_sensors); - - sensor = &data->sensors[data->num_sensors]; - snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s", - name, seq, type); - sensor->page = page; - sensor->reg = reg; - sensor->class = class; - sensor->update = update; - if (readonly) - PMBUS_ADD_GET_ATTR(data, sensor->name, sensor, - data->num_sensors); - else - PMBUS_ADD_SET_ATTR(data, sensor->name, sensor, - data->num_sensors); - data->num_sensors++; -} - -static void pmbus_add_label(struct pmbus_data *data, - const char *name, int seq, - const char *lstring, int index) -{ - struct pmbus_label *label; - - BUG_ON(data->num_labels >= data->max_labels); - - label = &data->labels[data->num_labels]; - snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq); - if (!index) - strncpy(label->label, lstring, sizeof(label->label) - 1); - else - snprintf(label->label, sizeof(label->label), "%s%d", lstring, - index); - - PMBUS_ADD_GET_ATTR(data, label->name, label, data->num_labels); - data->num_labels++; -} - -/* - * Determine maximum number of sensors, booleans, and labels. - * To keep things simple, only make a rough high estimate. - */ -static void pmbus_find_max_attr(struct i2c_client *client, - struct pmbus_data *data) -{ - const struct pmbus_driver_info *info = data->info; - int page, max_sensors, max_booleans, max_labels; - - max_sensors = PMBUS_MAX_INPUT_SENSORS; - max_booleans = PMBUS_MAX_INPUT_BOOLEANS; - max_labels = PMBUS_MAX_INPUT_LABELS; - - for (page = 0; page < info->pages; page++) { - if (info->func[page] & PMBUS_HAVE_VOUT) { - max_sensors += PMBUS_VOUT_SENSORS_PER_PAGE; - max_booleans += PMBUS_VOUT_BOOLEANS_PER_PAGE; - max_labels++; - } - if (info->func[page] & PMBUS_HAVE_IOUT) { - max_sensors += PMBUS_IOUT_SENSORS_PER_PAGE; - max_booleans += PMBUS_IOUT_BOOLEANS_PER_PAGE; - max_labels++; - } - if (info->func[page] & PMBUS_HAVE_POUT) { - max_sensors += PMBUS_POUT_SENSORS_PER_PAGE; - max_booleans += PMBUS_POUT_BOOLEANS_PER_PAGE; - max_labels++; - } - if (info->func[page] & PMBUS_HAVE_FAN12) { - max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN; - max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN; - } - if (info->func[page] & PMBUS_HAVE_FAN34) { - max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN; - max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN; - } - if (info->func[page] & PMBUS_HAVE_TEMP) { - max_sensors += PMBUS_MAX_SENSORS_PER_TEMP; - max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP; - } - if (info->func[page] & PMBUS_HAVE_TEMP2) { - max_sensors += PMBUS_MAX_SENSORS_PER_TEMP; - max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP; - } - if (info->func[page] & PMBUS_HAVE_TEMP3) { - max_sensors += PMBUS_MAX_SENSORS_PER_TEMP; - max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP; - } - } - data->max_sensors = max_sensors; - data->max_booleans = max_booleans; - data->max_labels = max_labels; - data->max_attributes = max_sensors + max_booleans + max_labels; -} - -/* - * Search for attributes. Allocate sensors, booleans, and labels as needed. - */ - -/* - * The pmbus_limit_attr structure describes a single limit attribute - * and its associated alarm attribute. - */ -struct pmbus_limit_attr { - u16 reg; /* Limit register */ - bool update; /* True if register needs updates */ - bool low; /* True if low limit; for limits with compare - functions only */ - const char *attr; /* Attribute name */ - const char *alarm; /* Alarm attribute name */ - u32 sbit; /* Alarm attribute status bit */ -}; - -/* - * The pmbus_sensor_attr structure describes one sensor attribute. This - * description includes a reference to the associated limit attributes. - */ -struct pmbus_sensor_attr { - u8 reg; /* sensor register */ - enum pmbus_sensor_classes class;/* sensor class */ - const char *label; /* sensor label */ - bool paged; /* true if paged sensor */ - bool update; /* true if update needed */ - bool compare; /* true if compare function needed */ - u32 func; /* sensor mask */ - u32 sfunc; /* sensor status mask */ - int sbase; /* status base register */ - u32 gbit; /* generic status bit */ - const struct pmbus_limit_attr *limit;/* limit registers */ - int nlimit; /* # of limit registers */ -}; - -/* - * Add a set of limit attributes and, if supported, the associated - * alarm attributes. - */ -static bool pmbus_add_limit_attrs(struct i2c_client *client, - struct pmbus_data *data, - const struct pmbus_driver_info *info, - const char *name, int index, int page, - int cbase, - const struct pmbus_sensor_attr *attr) -{ - const struct pmbus_limit_attr *l = attr->limit; - int nlimit = attr->nlimit; - bool have_alarm = false; - int i, cindex; - - for (i = 0; i < nlimit; i++) { - if (pmbus_check_word_register(client, page, l->reg)) { - cindex = data->num_sensors; - pmbus_add_sensor(data, name, l->attr, index, page, - l->reg, attr->class, - attr->update || l->update, - false); - if (l->sbit && (info->func[page] & attr->sfunc)) { - if (attr->compare) { - pmbus_add_boolean_cmp(data, name, - l->alarm, index, - l->low ? cindex : cbase, - l->low ? cbase : cindex, - attr->sbase + page, l->sbit); - } else { - pmbus_add_boolean_reg(data, name, - l->alarm, index, - attr->sbase + page, l->sbit); - } - have_alarm = true; - } - } - l++; - } - return have_alarm; -} - -static void pmbus_add_sensor_attrs_one(struct i2c_client *client, - struct pmbus_data *data, - const struct pmbus_driver_info *info, - const char *name, - int index, int page, - const struct pmbus_sensor_attr *attr) -{ - bool have_alarm; - int cbase = data->num_sensors; - - if (attr->label) - pmbus_add_label(data, name, index, attr->label, - attr->paged ? page + 1 : 0); - pmbus_add_sensor(data, name, "input", index, page, attr->reg, - attr->class, true, true); - if (attr->sfunc) { - have_alarm = pmbus_add_limit_attrs(client, data, info, name, - index, page, cbase, attr); - /* - * Add generic alarm attribute only if there are no individual - * alarm attributes, if there is a global alarm bit, and if - * the generic status register for this page is accessible. - */ - if (!have_alarm && attr->gbit && - pmbus_check_byte_register(client, page, PMBUS_STATUS_BYTE)) - pmbus_add_boolean_reg(data, name, "alarm", index, - PB_STATUS_BASE + page, - attr->gbit); - } -} - -static void pmbus_add_sensor_attrs(struct i2c_client *client, - struct pmbus_data *data, - const char *name, - const struct pmbus_sensor_attr *attrs, - int nattrs) -{ - const struct pmbus_driver_info *info = data->info; - int index, i; - - index = 1; - for (i = 0; i < nattrs; i++) { - int page, pages; - - pages = attrs->paged ? info->pages : 1; - for (page = 0; page < pages; page++) { - if (!(info->func[page] & attrs->func)) - continue; - pmbus_add_sensor_attrs_one(client, data, info, name, - index, page, attrs); - index++; - } - attrs++; - } -} - -static const struct pmbus_limit_attr vin_limit_attrs[] = { - { - .reg = PMBUS_VIN_UV_WARN_LIMIT, - .attr = "min", - .alarm = "min_alarm", - .sbit = PB_VOLTAGE_UV_WARNING, - }, { - .reg = PMBUS_VIN_UV_FAULT_LIMIT, - .attr = "lcrit", - .alarm = "lcrit_alarm", - .sbit = PB_VOLTAGE_UV_FAULT, - }, { - .reg = PMBUS_VIN_OV_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_VOLTAGE_OV_WARNING, - }, { - .reg = PMBUS_VIN_OV_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_VOLTAGE_OV_FAULT, - }, { - .reg = PMBUS_VIRT_READ_VIN_AVG, - .update = true, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_VIN_MIN, - .update = true, - .attr = "lowest", - }, { - .reg = PMBUS_VIRT_READ_VIN_MAX, - .update = true, - .attr = "highest", - }, { - .reg = PMBUS_VIRT_RESET_VIN_HISTORY, - .attr = "reset_history", - }, -}; - -static const struct pmbus_limit_attr vout_limit_attrs[] = { - { - .reg = PMBUS_VOUT_UV_WARN_LIMIT, - .attr = "min", - .alarm = "min_alarm", - .sbit = PB_VOLTAGE_UV_WARNING, - }, { - .reg = PMBUS_VOUT_UV_FAULT_LIMIT, - .attr = "lcrit", - .alarm = "lcrit_alarm", - .sbit = PB_VOLTAGE_UV_FAULT, - }, { - .reg = PMBUS_VOUT_OV_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_VOLTAGE_OV_WARNING, - }, { - .reg = PMBUS_VOUT_OV_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_VOLTAGE_OV_FAULT, - }, { - .reg = PMBUS_VIRT_READ_VOUT_AVG, - .update = true, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_VOUT_MIN, - .update = true, - .attr = "lowest", - }, { - .reg = PMBUS_VIRT_READ_VOUT_MAX, - .update = true, - .attr = "highest", - }, { - .reg = PMBUS_VIRT_RESET_VOUT_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_sensor_attr voltage_attributes[] = { - { - .reg = PMBUS_READ_VIN, - .class = PSC_VOLTAGE_IN, - .label = "vin", - .func = PMBUS_HAVE_VIN, - .sfunc = PMBUS_HAVE_STATUS_INPUT, - .sbase = PB_STATUS_INPUT_BASE, - .gbit = PB_STATUS_VIN_UV, - .limit = vin_limit_attrs, - .nlimit = ARRAY_SIZE(vin_limit_attrs), - }, { - .reg = PMBUS_READ_VCAP, - .class = PSC_VOLTAGE_IN, - .label = "vcap", - .func = PMBUS_HAVE_VCAP, - }, { - .reg = PMBUS_READ_VOUT, - .class = PSC_VOLTAGE_OUT, - .label = "vout", - .paged = true, - .func = PMBUS_HAVE_VOUT, - .sfunc = PMBUS_HAVE_STATUS_VOUT, - .sbase = PB_STATUS_VOUT_BASE, - .gbit = PB_STATUS_VOUT_OV, - .limit = vout_limit_attrs, - .nlimit = ARRAY_SIZE(vout_limit_attrs), - } -}; - -/* Current attributes */ - -static const struct pmbus_limit_attr iin_limit_attrs[] = { - { - .reg = PMBUS_IIN_OC_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_IIN_OC_WARNING, - }, { - .reg = PMBUS_IIN_OC_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_IIN_OC_FAULT, - }, { - .reg = PMBUS_VIRT_READ_IIN_AVG, - .update = true, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_IIN_MIN, - .update = true, - .attr = "lowest", - }, { - .reg = PMBUS_VIRT_READ_IIN_MAX, - .update = true, - .attr = "highest", - }, { - .reg = PMBUS_VIRT_RESET_IIN_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_limit_attr iout_limit_attrs[] = { - { - .reg = PMBUS_IOUT_OC_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_IOUT_OC_WARNING, - }, { - .reg = PMBUS_IOUT_UC_FAULT_LIMIT, - .attr = "lcrit", - .alarm = "lcrit_alarm", - .sbit = PB_IOUT_UC_FAULT, - }, { - .reg = PMBUS_IOUT_OC_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_IOUT_OC_FAULT, - }, { - .reg = PMBUS_VIRT_READ_IOUT_AVG, - .update = true, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_IOUT_MIN, - .update = true, - .attr = "lowest", - }, { - .reg = PMBUS_VIRT_READ_IOUT_MAX, - .update = true, - .attr = "highest", - }, { - .reg = PMBUS_VIRT_RESET_IOUT_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_sensor_attr current_attributes[] = { - { - .reg = PMBUS_READ_IIN, - .class = PSC_CURRENT_IN, - .label = "iin", - .func = PMBUS_HAVE_IIN, - .sfunc = PMBUS_HAVE_STATUS_INPUT, - .sbase = PB_STATUS_INPUT_BASE, - .limit = iin_limit_attrs, - .nlimit = ARRAY_SIZE(iin_limit_attrs), - }, { - .reg = PMBUS_READ_IOUT, - .class = PSC_CURRENT_OUT, - .label = "iout", - .paged = true, - .func = PMBUS_HAVE_IOUT, - .sfunc = PMBUS_HAVE_STATUS_IOUT, - .sbase = PB_STATUS_IOUT_BASE, - .gbit = PB_STATUS_IOUT_OC, - .limit = iout_limit_attrs, - .nlimit = ARRAY_SIZE(iout_limit_attrs), - } -}; - -/* Power attributes */ - -static const struct pmbus_limit_attr pin_limit_attrs[] = { - { - .reg = PMBUS_PIN_OP_WARN_LIMIT, - .attr = "max", - .alarm = "alarm", - .sbit = PB_PIN_OP_WARNING, - }, { - .reg = PMBUS_VIRT_READ_PIN_AVG, - .update = true, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_PIN_MAX, - .update = true, - .attr = "input_highest", - }, { - .reg = PMBUS_VIRT_RESET_PIN_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_limit_attr pout_limit_attrs[] = { - { - .reg = PMBUS_POUT_MAX, - .attr = "cap", - .alarm = "cap_alarm", - .sbit = PB_POWER_LIMITING, - }, { - .reg = PMBUS_POUT_OP_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_POUT_OP_WARNING, - }, { - .reg = PMBUS_POUT_OP_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_POUT_OP_FAULT, - }, { - .reg = PMBUS_VIRT_READ_POUT_AVG, - .update = true, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_POUT_MAX, - .update = true, - .attr = "input_highest", - }, { - .reg = PMBUS_VIRT_RESET_POUT_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_sensor_attr power_attributes[] = { - { - .reg = PMBUS_READ_PIN, - .class = PSC_POWER, - .label = "pin", - .func = PMBUS_HAVE_PIN, - .sfunc = PMBUS_HAVE_STATUS_INPUT, - .sbase = PB_STATUS_INPUT_BASE, - .limit = pin_limit_attrs, - .nlimit = ARRAY_SIZE(pin_limit_attrs), - }, { - .reg = PMBUS_READ_POUT, - .class = PSC_POWER, - .label = "pout", - .paged = true, - .func = PMBUS_HAVE_POUT, - .sfunc = PMBUS_HAVE_STATUS_IOUT, - .sbase = PB_STATUS_IOUT_BASE, - .limit = pout_limit_attrs, - .nlimit = ARRAY_SIZE(pout_limit_attrs), - } -}; - -/* Temperature atributes */ - -static const struct pmbus_limit_attr temp_limit_attrs[] = { - { - .reg = PMBUS_UT_WARN_LIMIT, - .low = true, - .attr = "min", - .alarm = "min_alarm", - .sbit = PB_TEMP_UT_WARNING, - }, { - .reg = PMBUS_UT_FAULT_LIMIT, - .low = true, - .attr = "lcrit", - .alarm = "lcrit_alarm", - .sbit = PB_TEMP_UT_FAULT, - }, { - .reg = PMBUS_OT_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_TEMP_OT_WARNING, - }, { - .reg = PMBUS_OT_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_TEMP_OT_FAULT, - }, { - .reg = PMBUS_VIRT_READ_TEMP_MIN, - .attr = "lowest", - }, { - .reg = PMBUS_VIRT_READ_TEMP_AVG, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_TEMP_MAX, - .attr = "highest", - }, { - .reg = PMBUS_VIRT_RESET_TEMP_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_limit_attr temp_limit_attrs2[] = { - { - .reg = PMBUS_UT_WARN_LIMIT, - .low = true, - .attr = "min", - .alarm = "min_alarm", - .sbit = PB_TEMP_UT_WARNING, - }, { - .reg = PMBUS_UT_FAULT_LIMIT, - .low = true, - .attr = "lcrit", - .alarm = "lcrit_alarm", - .sbit = PB_TEMP_UT_FAULT, - }, { - .reg = PMBUS_OT_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_TEMP_OT_WARNING, - }, { - .reg = PMBUS_OT_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_TEMP_OT_FAULT, - }, { - .reg = PMBUS_VIRT_READ_TEMP2_MIN, - .attr = "lowest", - }, { - .reg = PMBUS_VIRT_READ_TEMP2_AVG, - .attr = "average", - }, { - .reg = PMBUS_VIRT_READ_TEMP2_MAX, - .attr = "highest", - }, { - .reg = PMBUS_VIRT_RESET_TEMP2_HISTORY, - .attr = "reset_history", - } -}; - -static const struct pmbus_limit_attr temp_limit_attrs3[] = { - { - .reg = PMBUS_UT_WARN_LIMIT, - .low = true, - .attr = "min", - .alarm = "min_alarm", - .sbit = PB_TEMP_UT_WARNING, - }, { - .reg = PMBUS_UT_FAULT_LIMIT, - .low = true, - .attr = "lcrit", - .alarm = "lcrit_alarm", - .sbit = PB_TEMP_UT_FAULT, - }, { - .reg = PMBUS_OT_WARN_LIMIT, - .attr = "max", - .alarm = "max_alarm", - .sbit = PB_TEMP_OT_WARNING, - }, { - .reg = PMBUS_OT_FAULT_LIMIT, - .attr = "crit", - .alarm = "crit_alarm", - .sbit = PB_TEMP_OT_FAULT, - } -}; - -static const struct pmbus_sensor_attr temp_attributes[] = { - { - .reg = PMBUS_READ_TEMPERATURE_1, - .class = PSC_TEMPERATURE, - .paged = true, - .update = true, - .compare = true, - .func = PMBUS_HAVE_TEMP, - .sfunc = PMBUS_HAVE_STATUS_TEMP, - .sbase = PB_STATUS_TEMP_BASE, - .gbit = PB_STATUS_TEMPERATURE, - .limit = temp_limit_attrs, - .nlimit = ARRAY_SIZE(temp_limit_attrs), - }, { - .reg = PMBUS_READ_TEMPERATURE_2, - .class = PSC_TEMPERATURE, - .paged = true, - .update = true, - .compare = true, - .func = PMBUS_HAVE_TEMP2, - .sfunc = PMBUS_HAVE_STATUS_TEMP, - .sbase = PB_STATUS_TEMP_BASE, - .gbit = PB_STATUS_TEMPERATURE, - .limit = temp_limit_attrs2, - .nlimit = ARRAY_SIZE(temp_limit_attrs2), - }, { - .reg = PMBUS_READ_TEMPERATURE_3, - .class = PSC_TEMPERATURE, - .paged = true, - .update = true, - .compare = true, - .func = PMBUS_HAVE_TEMP3, - .sfunc = PMBUS_HAVE_STATUS_TEMP, - .sbase = PB_STATUS_TEMP_BASE, - .gbit = PB_STATUS_TEMPERATURE, - .limit = temp_limit_attrs3, - .nlimit = ARRAY_SIZE(temp_limit_attrs3), - } -}; - -static const int pmbus_fan_registers[] = { - PMBUS_READ_FAN_SPEED_1, - PMBUS_READ_FAN_SPEED_2, - PMBUS_READ_FAN_SPEED_3, - PMBUS_READ_FAN_SPEED_4 -}; - -static const int pmbus_fan_config_registers[] = { - PMBUS_FAN_CONFIG_12, - PMBUS_FAN_CONFIG_12, - PMBUS_FAN_CONFIG_34, - PMBUS_FAN_CONFIG_34 -}; - -static const int pmbus_fan_status_registers[] = { - PMBUS_STATUS_FAN_12, - PMBUS_STATUS_FAN_12, - PMBUS_STATUS_FAN_34, - PMBUS_STATUS_FAN_34 -}; - -static const u32 pmbus_fan_flags[] = { - PMBUS_HAVE_FAN12, - PMBUS_HAVE_FAN12, - PMBUS_HAVE_FAN34, - PMBUS_HAVE_FAN34 -}; - -static const u32 pmbus_fan_status_flags[] = { - PMBUS_HAVE_STATUS_FAN12, - PMBUS_HAVE_STATUS_FAN12, - PMBUS_HAVE_STATUS_FAN34, - PMBUS_HAVE_STATUS_FAN34 -}; - -/* Fans */ -static void pmbus_add_fan_attributes(struct i2c_client *client, - struct pmbus_data *data) -{ - const struct pmbus_driver_info *info = data->info; - int index = 1; - int page; - - for (page = 0; page < info->pages; page++) { - int f; - - for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) { - int regval; - - if (!(info->func[page] & pmbus_fan_flags[f])) - break; - - if (!pmbus_check_word_register(client, page, - pmbus_fan_registers[f])) - break; - - /* - * Skip fan if not installed. - * Each fan configuration register covers multiple fans, - * so we have to do some magic. - */ - regval = _pmbus_read_byte_data(client, page, - pmbus_fan_config_registers[f]); - if (regval < 0 || - (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4))))) - continue; - - pmbus_add_sensor(data, "fan", "input", index, page, - pmbus_fan_registers[f], PSC_FAN, true, - true); - - /* - * Each fan status register covers multiple fans, - * so we have to do some magic. - */ - if ((info->func[page] & pmbus_fan_status_flags[f]) && - pmbus_check_byte_register(client, - page, pmbus_fan_status_registers[f])) { - int base; - - if (f > 1) /* fan 3, 4 */ - base = PB_STATUS_FAN34_BASE + page; - else - base = PB_STATUS_FAN_BASE + page; - pmbus_add_boolean_reg(data, "fan", "alarm", - index, base, - PB_FAN_FAN1_WARNING >> (f & 1)); - pmbus_add_boolean_reg(data, "fan", "fault", - index, base, - PB_FAN_FAN1_FAULT >> (f & 1)); - } - index++; - } - } -} - -static void pmbus_find_attributes(struct i2c_client *client, - struct pmbus_data *data) -{ - /* Voltage sensors */ - pmbus_add_sensor_attrs(client, data, "in", voltage_attributes, - ARRAY_SIZE(voltage_attributes)); - - /* Current sensors */ - pmbus_add_sensor_attrs(client, data, "curr", current_attributes, - ARRAY_SIZE(current_attributes)); - - /* Power sensors */ - pmbus_add_sensor_attrs(client, data, "power", power_attributes, - ARRAY_SIZE(power_attributes)); - - /* Temperature sensors */ - pmbus_add_sensor_attrs(client, data, "temp", temp_attributes, - ARRAY_SIZE(temp_attributes)); - - /* Fans */ - pmbus_add_fan_attributes(client, data); -} - -/* - * Identify chip parameters. - * This function is called for all chips. - */ -static int pmbus_identify_common(struct i2c_client *client, - struct pmbus_data *data) -{ - int vout_mode = -1; - - if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE)) - vout_mode = _pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE); - if (vout_mode >= 0 && vout_mode != 0xff) { - /* - * Not all chips support the VOUT_MODE command, - * so a failure to read it is not an error. - */ - switch (vout_mode >> 5) { - case 0: /* linear mode */ - if (data->info->format[PSC_VOLTAGE_OUT] != linear) - return -ENODEV; - - data->exponent = ((s8)(vout_mode << 3)) >> 3; - break; - case 1: /* VID mode */ - if (data->info->format[PSC_VOLTAGE_OUT] != vid) - return -ENODEV; - break; - case 2: /* direct mode */ - if (data->info->format[PSC_VOLTAGE_OUT] != direct) - return -ENODEV; - break; - default: - return -ENODEV; - } - } - - /* Determine maximum number of sensors, booleans, and labels */ - pmbus_find_max_attr(client, data); - pmbus_clear_fault_page(client, 0); - return 0; -} - -int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, - struct pmbus_driver_info *info) -{ - const struct pmbus_platform_data *pdata = client->dev.platform_data; - struct pmbus_data *data; - int ret; - - if (!info) { - dev_err(&client->dev, "Missing chip information"); - return -ENODEV; - } - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE - | I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "No memory to allocate driver data\n"); - return -ENOMEM; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Bail out if PMBus status register does not exist. */ - if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0) { - dev_err(&client->dev, "PMBus status register not found\n"); - return -ENODEV; - } - - if (pdata) - data->flags = pdata->flags; - data->info = info; - - pmbus_clear_faults(client); - - if (info->identify) { - ret = (*info->identify)(client, info); - if (ret < 0) { - dev_err(&client->dev, "Chip identification failed\n"); - return ret; - } - } - - if (info->pages <= 0 || info->pages > PMBUS_PAGES) { - dev_err(&client->dev, "Bad number of PMBus pages: %d\n", - info->pages); - return -ENODEV; - } - - ret = pmbus_identify_common(client, data); - if (ret < 0) { - dev_err(&client->dev, "Failed to identify chip capabilities\n"); - return ret; - } - - ret = -ENOMEM; - data->sensors = devm_kzalloc(&client->dev, sizeof(struct pmbus_sensor) - * data->max_sensors, GFP_KERNEL); - if (!data->sensors) { - dev_err(&client->dev, "No memory to allocate sensor data\n"); - return -ENOMEM; - } - - data->booleans = devm_kzalloc(&client->dev, sizeof(struct pmbus_boolean) - * data->max_booleans, GFP_KERNEL); - if (!data->booleans) { - dev_err(&client->dev, "No memory to allocate boolean data\n"); - return -ENOMEM; - } - - data->labels = devm_kzalloc(&client->dev, sizeof(struct pmbus_label) - * data->max_labels, GFP_KERNEL); - if (!data->labels) { - dev_err(&client->dev, "No memory to allocate label data\n"); - return -ENOMEM; - } - - data->attributes = devm_kzalloc(&client->dev, sizeof(struct attribute *) - * data->max_attributes, GFP_KERNEL); - if (!data->attributes) { - dev_err(&client->dev, "No memory to allocate attribute data\n"); - return -ENOMEM; - } - - pmbus_find_attributes(client, data); - - /* - * If there are no attributes, something is wrong. - * Bail out instead of trying to register nothing. - */ - if (!data->num_attributes) { - dev_err(&client->dev, "No attributes found\n"); - return -ENODEV; - } - - /* Register sysfs hooks */ - data->group.attrs = data->attributes; - ret = sysfs_create_group(&client->dev.kobj, &data->group); - if (ret) { - dev_err(&client->dev, "Failed to create sysfs entries\n"); - return ret; - } - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "Failed to register hwmon device\n"); - goto out_hwmon_device_register; - } - return 0; - -out_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, &data->group); - return ret; -} -EXPORT_SYMBOL_GPL(pmbus_do_probe); - -int pmbus_do_remove(struct i2c_client *client) -{ - struct pmbus_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->group); - return 0; -} -EXPORT_SYMBOL_GPL(pmbus_do_remove); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus core driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9000.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9000.c deleted file mode 100644 index fbb1479d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9000.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Hardware monitoring driver for UCD90xxx Sequencer and System Health - * Controller series - * - * Copyright (C) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -enum chips { ucd9000, ucd90120, ucd90124, ucd9090, ucd90910 }; - -#define UCD9000_MONITOR_CONFIG 0xd5 -#define UCD9000_NUM_PAGES 0xd6 -#define UCD9000_FAN_CONFIG_INDEX 0xe7 -#define UCD9000_FAN_CONFIG 0xe8 -#define UCD9000_DEVICE_ID 0xfd - -#define UCD9000_MON_TYPE(x) (((x) >> 5) & 0x07) -#define UCD9000_MON_PAGE(x) ((x) & 0x0f) - -#define UCD9000_MON_VOLTAGE 1 -#define UCD9000_MON_TEMPERATURE 2 -#define UCD9000_MON_CURRENT 3 -#define UCD9000_MON_VOLTAGE_HW 4 - -#define UCD9000_NUM_FAN 4 - -struct ucd9000_data { - u8 fan_data[UCD9000_NUM_FAN][I2C_SMBUS_BLOCK_MAX]; - struct pmbus_driver_info info; -}; -#define to_ucd9000_data(_info) container_of(_info, struct ucd9000_data, info) - -static int ucd9000_get_fan_config(struct i2c_client *client, int fan) -{ - int fan_config = 0; - struct ucd9000_data *data - = to_ucd9000_data(pmbus_get_driver_info(client)); - - if (data->fan_data[fan][3] & 1) - fan_config |= PB_FAN_2_INSTALLED; /* Use lower bit position */ - - /* Pulses/revolution */ - fan_config |= (data->fan_data[fan][3] & 0x06) >> 1; - - return fan_config; -} - -static int ucd9000_read_byte_data(struct i2c_client *client, int page, int reg) -{ - int ret = 0; - int fan_config; - - switch (reg) { - case PMBUS_FAN_CONFIG_12: - if (page > 0) - return -ENXIO; - - ret = ucd9000_get_fan_config(client, 0); - if (ret < 0) - return ret; - fan_config = ret << 4; - ret = ucd9000_get_fan_config(client, 1); - if (ret < 0) - return ret; - fan_config |= ret; - ret = fan_config; - break; - case PMBUS_FAN_CONFIG_34: - if (page > 0) - return -ENXIO; - - ret = ucd9000_get_fan_config(client, 2); - if (ret < 0) - return ret; - fan_config = ret << 4; - ret = ucd9000_get_fan_config(client, 3); - if (ret < 0) - return ret; - fan_config |= ret; - ret = fan_config; - break; - default: - ret = -ENODATA; - break; - } - return ret; -} - -static const struct i2c_device_id ucd9000_id[] = { - {"ucd9000", ucd9000}, - {"ucd90120", ucd90120}, - {"ucd90124", ucd90124}, - {"ucd9090", ucd9090}, - {"ucd90910", ucd90910}, - {} -}; -MODULE_DEVICE_TABLE(i2c, ucd9000_id); - -static int ucd9000_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; - struct ucd9000_data *data; - struct pmbus_driver_info *info; - const struct i2c_device_id *mid; - int i, ret; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA)) - return -ENODEV; - - ret = i2c_smbus_read_block_data(client, UCD9000_DEVICE_ID, - block_buffer); - if (ret < 0) { - dev_err(&client->dev, "Failed to read device ID\n"); - return ret; - } - block_buffer[ret] = '\0'; - dev_info(&client->dev, "Device ID %s\n", block_buffer); - - for (mid = ucd9000_id; mid->name[0]; mid++) { - if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) - break; - } - if (!mid->name[0]) { - dev_err(&client->dev, "Unsupported device\n"); - return -ENODEV; - } - - if (id->driver_data != ucd9000 && id->driver_data != mid->driver_data) - dev_notice(&client->dev, - "Device mismatch: Configured %s, detected %s\n", - id->name, mid->name); - - data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - info = &data->info; - - ret = i2c_smbus_read_byte_data(client, UCD9000_NUM_PAGES); - if (ret < 0) { - dev_err(&client->dev, - "Failed to read number of active pages\n"); - return ret; - } - info->pages = ret; - if (!info->pages) { - dev_err(&client->dev, "No pages configured\n"); - return -ENODEV; - } - - /* The internal temperature sensor is always active */ - info->func[0] = PMBUS_HAVE_TEMP; - - /* Everything else is configurable */ - ret = i2c_smbus_read_block_data(client, UCD9000_MONITOR_CONFIG, - block_buffer); - if (ret <= 0) { - dev_err(&client->dev, "Failed to read configuration data\n"); - return -ENODEV; - } - for (i = 0; i < ret; i++) { - int page = UCD9000_MON_PAGE(block_buffer[i]); - - if (page >= info->pages) - continue; - - switch (UCD9000_MON_TYPE(block_buffer[i])) { - case UCD9000_MON_VOLTAGE: - case UCD9000_MON_VOLTAGE_HW: - info->func[page] |= PMBUS_HAVE_VOUT - | PMBUS_HAVE_STATUS_VOUT; - break; - case UCD9000_MON_TEMPERATURE: - info->func[page] |= PMBUS_HAVE_TEMP2 - | PMBUS_HAVE_STATUS_TEMP; - break; - case UCD9000_MON_CURRENT: - info->func[page] |= PMBUS_HAVE_IOUT - | PMBUS_HAVE_STATUS_IOUT; - break; - default: - break; - } - } - - /* Fan configuration */ - if (mid->driver_data == ucd90124) { - for (i = 0; i < UCD9000_NUM_FAN; i++) { - i2c_smbus_write_byte_data(client, - UCD9000_FAN_CONFIG_INDEX, i); - ret = i2c_smbus_read_block_data(client, - UCD9000_FAN_CONFIG, - data->fan_data[i]); - if (ret < 0) - return ret; - } - i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0); - - info->read_byte_data = ucd9000_read_byte_data; - info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12 - | PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34; - } - - return pmbus_do_probe(client, mid, info); -} - -/* This is the driver that will be inserted */ -static struct i2c_driver ucd9000_driver = { - .driver = { - .name = "ucd9000", - }, - .probe = ucd9000_probe, - .remove = pmbus_do_remove, - .id_table = ucd9000_id, -}; - -module_i2c_driver(ucd9000_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9200.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9200.c deleted file mode 100644 index 033d6aca..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/ucd9200.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Hardware monitoring driver for ucd9200 series Digital PWM System Controllers - * - * Copyright (C) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -#define UCD9200_PHASE_INFO 0xd2 -#define UCD9200_DEVICE_ID 0xfd - -enum chips { ucd9200, ucd9220, ucd9222, ucd9224, ucd9240, ucd9244, ucd9246, - ucd9248 }; - -static const struct i2c_device_id ucd9200_id[] = { - {"ucd9200", ucd9200}, - {"ucd9220", ucd9220}, - {"ucd9222", ucd9222}, - {"ucd9224", ucd9224}, - {"ucd9240", ucd9240}, - {"ucd9244", ucd9244}, - {"ucd9246", ucd9246}, - {"ucd9248", ucd9248}, - {} -}; -MODULE_DEVICE_TABLE(i2c, ucd9200_id); - -static int ucd9200_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - u8 block_buffer[I2C_SMBUS_BLOCK_MAX + 1]; - struct pmbus_driver_info *info; - const struct i2c_device_id *mid; - int i, j, ret; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_BLOCK_DATA)) - return -ENODEV; - - ret = i2c_smbus_read_block_data(client, UCD9200_DEVICE_ID, - block_buffer); - if (ret < 0) { - dev_err(&client->dev, "Failed to read device ID\n"); - return ret; - } - block_buffer[ret] = '\0'; - dev_info(&client->dev, "Device ID %s\n", block_buffer); - - for (mid = ucd9200_id; mid->name[0]; mid++) { - if (!strncasecmp(mid->name, block_buffer, strlen(mid->name))) - break; - } - if (!mid->name[0]) { - dev_err(&client->dev, "Unsupported device\n"); - return -ENODEV; - } - if (id->driver_data != ucd9200 && id->driver_data != mid->driver_data) - dev_notice(&client->dev, - "Device mismatch: Configured %s, detected %s\n", - id->name, mid->name); - - info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info), - GFP_KERNEL); - if (!info) - return -ENOMEM; - - ret = i2c_smbus_read_block_data(client, UCD9200_PHASE_INFO, - block_buffer); - if (ret < 0) { - dev_err(&client->dev, "Failed to read phase information\n"); - return ret; - } - - /* - * Calculate number of configured pages (rails) from PHASE_INFO - * register. - * Rails have to be sequential, so we can abort after finding - * the first unconfigured rail. - */ - info->pages = 0; - for (i = 0; i < ret; i++) { - if (!block_buffer[i]) - break; - info->pages++; - } - if (!info->pages) { - dev_err(&client->dev, "No rails configured\n"); - return -ENODEV; - } - dev_info(&client->dev, "%d rails configured\n", info->pages); - - /* - * Set PHASE registers on all pages to 0xff to ensure that phase - * specific commands will apply to all phases of a given page (rail). - * This only affects the READ_IOUT and READ_TEMPERATURE2 registers. - * READ_IOUT will return the sum of currents of all phases of a rail, - * and READ_TEMPERATURE2 will return the maximum temperature detected - * for the the phases of the rail. - */ - for (i = 0; i < info->pages; i++) { - /* - * Setting PAGE & PHASE fails once in a while for no obvious - * reason, so we need to retry a couple of times. - */ - for (j = 0; j < 3; j++) { - ret = i2c_smbus_write_byte_data(client, PMBUS_PAGE, i); - if (ret < 0) - continue; - ret = i2c_smbus_write_byte_data(client, PMBUS_PHASE, - 0xff); - if (ret < 0) - continue; - break; - } - if (ret < 0) { - dev_err(&client->dev, - "Failed to initialize PHASE registers\n"); - return ret; - } - } - if (info->pages > 1) - i2c_smbus_write_byte_data(client, PMBUS_PAGE, 0); - - info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT | - PMBUS_HAVE_IIN | PMBUS_HAVE_PIN | - PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | - PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | - PMBUS_HAVE_POUT | PMBUS_HAVE_TEMP | - PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; - - for (i = 1; i < info->pages; i++) - info->func[i] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT | - PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | - PMBUS_HAVE_POUT | - PMBUS_HAVE_TEMP2 | PMBUS_HAVE_STATUS_TEMP; - - /* ucd9240 supports a single fan */ - if (mid->driver_data == ucd9240) - info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12; - - return pmbus_do_probe(client, mid, info); -} - -/* This is the driver that will be inserted */ -static struct i2c_driver ucd9200_driver = { - .driver = { - .name = "ucd9200", - }, - .probe = ucd9200_probe, - .remove = pmbus_do_remove, - .id_table = ucd9200_id, -}; - -module_i2c_driver(ucd9200_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/pmbus/zl6100.c b/ANDROID_3.4.5/drivers/hwmon/pmbus/zl6100.c deleted file mode 100644 index fc5eed8e..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/pmbus/zl6100.c +++ /dev/null @@ -1,259 +0,0 @@ -/* - * Hardware monitoring driver for ZL6100 and compatibles - * - * Copyright (c) 2011 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "pmbus.h" - -enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105, - zl9101, zl9117 }; - -struct zl6100_data { - int id; - ktime_t access; /* chip access time */ - int delay; /* Delay between chip accesses in uS */ - struct pmbus_driver_info info; -}; - -#define to_zl6100_data(x) container_of(x, struct zl6100_data, info) - -#define ZL6100_MFR_CONFIG 0xd0 -#define ZL6100_DEVICE_ID 0xe4 - -#define ZL6100_MFR_XTEMP_ENABLE (1 << 7) - -#define ZL6100_WAIT_TIME 1000 /* uS */ - -static ushort delay = ZL6100_WAIT_TIME; -module_param(delay, ushort, 0644); -MODULE_PARM_DESC(delay, "Delay between chip accesses in uS"); - -/* Some chips need a delay between accesses */ -static inline void zl6100_wait(const struct zl6100_data *data) -{ - if (data->delay) { - s64 delta = ktime_us_delta(ktime_get(), data->access); - if (delta < data->delay) - udelay(data->delay - delta); - } -} - -static int zl6100_read_word_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct zl6100_data *data = to_zl6100_data(info); - int ret; - - if (page || reg >= PMBUS_VIRT_BASE) - return -ENXIO; - - if (data->id == zl2005) { - /* - * Limit register detection is not reliable on ZL2005. - * Make sure registers are not erroneously detected. - */ - switch (reg) { - case PMBUS_VOUT_OV_WARN_LIMIT: - case PMBUS_VOUT_UV_WARN_LIMIT: - case PMBUS_IOUT_OC_WARN_LIMIT: - return -ENXIO; - } - } - - zl6100_wait(data); - ret = pmbus_read_word_data(client, page, reg); - data->access = ktime_get(); - - return ret; -} - -static int zl6100_read_byte_data(struct i2c_client *client, int page, int reg) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct zl6100_data *data = to_zl6100_data(info); - int ret; - - if (page > 0) - return -ENXIO; - - zl6100_wait(data); - ret = pmbus_read_byte_data(client, page, reg); - data->access = ktime_get(); - - return ret; -} - -static int zl6100_write_word_data(struct i2c_client *client, int page, int reg, - u16 word) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct zl6100_data *data = to_zl6100_data(info); - int ret; - - if (page || reg >= PMBUS_VIRT_BASE) - return -ENXIO; - - zl6100_wait(data); - ret = pmbus_write_word_data(client, page, reg, word); - data->access = ktime_get(); - - return ret; -} - -static int zl6100_write_byte(struct i2c_client *client, int page, u8 value) -{ - const struct pmbus_driver_info *info = pmbus_get_driver_info(client); - struct zl6100_data *data = to_zl6100_data(info); - int ret; - - if (page > 0) - return -ENXIO; - - zl6100_wait(data); - ret = pmbus_write_byte(client, page, value); - data->access = ktime_get(); - - return ret; -} - -static const struct i2c_device_id zl6100_id[] = { - {"bmr450", zl2005}, - {"bmr451", zl2005}, - {"bmr462", zl2008}, - {"bmr463", zl2008}, - {"bmr464", zl2008}, - {"zl2004", zl2004}, - {"zl2005", zl2005}, - {"zl2006", zl2006}, - {"zl2008", zl2008}, - {"zl2105", zl2105}, - {"zl2106", zl2106}, - {"zl6100", zl6100}, - {"zl6105", zl6105}, - {"zl9101", zl9101}, - {"zl9117", zl9117}, - { } -}; -MODULE_DEVICE_TABLE(i2c, zl6100_id); - -static int zl6100_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int ret; - struct zl6100_data *data; - struct pmbus_driver_info *info; - u8 device_id[I2C_SMBUS_BLOCK_MAX + 1]; - const struct i2c_device_id *mid; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_READ_WORD_DATA - | I2C_FUNC_SMBUS_READ_BLOCK_DATA)) - return -ENODEV; - - ret = i2c_smbus_read_block_data(client, ZL6100_DEVICE_ID, - device_id); - if (ret < 0) { - dev_err(&client->dev, "Failed to read device ID\n"); - return ret; - } - device_id[ret] = '\0'; - dev_info(&client->dev, "Device ID %s\n", device_id); - - mid = NULL; - for (mid = zl6100_id; mid->name[0]; mid++) { - if (!strncasecmp(mid->name, device_id, strlen(mid->name))) - break; - } - if (!mid->name[0]) { - dev_err(&client->dev, "Unsupported device\n"); - return -ENODEV; - } - if (id->driver_data != mid->driver_data) - dev_notice(&client->dev, - "Device mismatch: Configured %s, detected %s\n", - id->name, mid->name); - - data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->id = mid->driver_data; - - /* - * According to information from the chip vendor, all currently - * supported chips are known to require a wait time between I2C - * accesses. - */ - data->delay = delay; - - /* - * Since there was a direct I2C device access above, wait before - * accessing the chip again. - */ - data->access = ktime_get(); - zl6100_wait(data); - - info = &data->info; - - info->pages = 1; - info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_STATUS_INPUT - | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT - | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT - | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; - - ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG); - if (ret < 0) - return ret; - - if (ret & ZL6100_MFR_XTEMP_ENABLE) - info->func[0] |= PMBUS_HAVE_TEMP2; - - data->access = ktime_get(); - zl6100_wait(data); - - info->read_word_data = zl6100_read_word_data; - info->read_byte_data = zl6100_read_byte_data; - info->write_word_data = zl6100_write_word_data; - info->write_byte = zl6100_write_byte; - - return pmbus_do_probe(client, mid, info); -} - -static struct i2c_driver zl6100_driver = { - .driver = { - .name = "zl6100", - }, - .probe = zl6100_probe, - .remove = pmbus_do_remove, - .id_table = zl6100_id, -}; - -module_i2c_driver(zl6100_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/s3c-hwmon.c b/ANDROID_3.4.5/drivers/hwmon/s3c-hwmon.c deleted file mode 100644 index f6c26d19..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/s3c-hwmon.c +++ /dev/null @@ -1,401 +0,0 @@ -/* linux/drivers/hwmon/s3c-hwmon.c - * - * Copyright (C) 2005, 2008, 2009 Simtec Electronics - * http://armlinux.simtec.co.uk/ - * Ben Dooks - * - * S3C24XX/S3C64XX ADC hwmon support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -struct s3c_hwmon_attr { - struct sensor_device_attribute in; - struct sensor_device_attribute label; - char in_name[12]; - char label_name[12]; -}; - -/** - * struct s3c_hwmon - ADC hwmon client information - * @lock: Access lock to serialise the conversions. - * @client: The client we registered with the S3C ADC core. - * @hwmon_dev: The hwmon device we created. - * @attr: The holders for the channel attributes. -*/ -struct s3c_hwmon { - struct mutex lock; - struct s3c_adc_client *client; - struct device *hwmon_dev; - - struct s3c_hwmon_attr attrs[8]; -}; - -/** - * s3c_hwmon_read_ch - read a value from a given adc channel. - * @dev: The device. - * @hwmon: Our state. - * @channel: The channel we're reading from. - * - * Read a value from the @channel with the proper locking and sleep until - * either the read completes or we timeout awaiting the ADC core to get - * back to us. - */ -static int s3c_hwmon_read_ch(struct device *dev, - struct s3c_hwmon *hwmon, int channel) -{ - int ret; - - ret = mutex_lock_interruptible(&hwmon->lock); - if (ret < 0) - return ret; - - dev_dbg(dev, "reading channel %d\n", channel); - - ret = s3c_adc_read(hwmon->client, channel); - mutex_unlock(&hwmon->lock); - - return ret; -} - -#ifdef CONFIG_SENSORS_S3C_RAW -/** - * s3c_hwmon_show_raw - show a conversion from the raw channel number. - * @dev: The device that the attribute belongs to. - * @attr: The attribute being read. - * @buf: The result buffer. - * - * This show deals with the raw attribute, registered for each possible - * ADC channel. This does a conversion and returns the raw (un-scaled) - * value returned from the hardware. - */ -static ssize_t s3c_hwmon_show_raw(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct s3c_hwmon *adc = platform_get_drvdata(to_platform_device(dev)); - struct sensor_device_attribute *sa = to_sensor_dev_attr(attr); - int ret; - - ret = s3c_hwmon_read_ch(dev, adc, sa->index); - - return (ret < 0) ? ret : snprintf(buf, PAGE_SIZE, "%d\n", ret); -} - -#define DEF_ADC_ATTR(x) \ - static SENSOR_DEVICE_ATTR(adc##x##_raw, S_IRUGO, s3c_hwmon_show_raw, NULL, x) - -DEF_ADC_ATTR(0); -DEF_ADC_ATTR(1); -DEF_ADC_ATTR(2); -DEF_ADC_ATTR(3); -DEF_ADC_ATTR(4); -DEF_ADC_ATTR(5); -DEF_ADC_ATTR(6); -DEF_ADC_ATTR(7); - -static struct attribute *s3c_hwmon_attrs[9] = { - &sensor_dev_attr_adc0_raw.dev_attr.attr, - &sensor_dev_attr_adc1_raw.dev_attr.attr, - &sensor_dev_attr_adc2_raw.dev_attr.attr, - &sensor_dev_attr_adc3_raw.dev_attr.attr, - &sensor_dev_attr_adc4_raw.dev_attr.attr, - &sensor_dev_attr_adc5_raw.dev_attr.attr, - &sensor_dev_attr_adc6_raw.dev_attr.attr, - &sensor_dev_attr_adc7_raw.dev_attr.attr, - NULL, -}; - -static struct attribute_group s3c_hwmon_attrgroup = { - .attrs = s3c_hwmon_attrs, -}; - -static inline int s3c_hwmon_add_raw(struct device *dev) -{ - return sysfs_create_group(&dev->kobj, &s3c_hwmon_attrgroup); -} - -static inline void s3c_hwmon_remove_raw(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &s3c_hwmon_attrgroup); -} - -#else - -static inline int s3c_hwmon_add_raw(struct device *dev) { return 0; } -static inline void s3c_hwmon_remove_raw(struct device *dev) { } - -#endif /* CONFIG_SENSORS_S3C_RAW */ - -/** - * s3c_hwmon_ch_show - show value of a given channel - * @dev: The device that the attribute belongs to. - * @attr: The attribute being read. - * @buf: The result buffer. - * - * Read a value from the ADC and scale it before returning it to the - * caller. The scale factor is gained from the channel configuration - * passed via the platform data when the device was registered. - */ -static ssize_t s3c_hwmon_ch_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sen_attr = to_sensor_dev_attr(attr); - struct s3c_hwmon *hwmon = platform_get_drvdata(to_platform_device(dev)); - struct s3c_hwmon_pdata *pdata = dev->platform_data; - struct s3c_hwmon_chcfg *cfg; - int ret; - - cfg = pdata->in[sen_attr->index]; - - ret = s3c_hwmon_read_ch(dev, hwmon, sen_attr->index); - if (ret < 0) - return ret; - - ret *= cfg->mult; - ret = DIV_ROUND_CLOSEST(ret, cfg->div); - - return snprintf(buf, PAGE_SIZE, "%d\n", ret); -} - -/** - * s3c_hwmon_label_show - show label name of the given channel. - * @dev: The device that the attribute belongs to. - * @attr: The attribute being read. - * @buf: The result buffer. - * - * Return the label name of a given channel - */ -static ssize_t s3c_hwmon_label_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sen_attr = to_sensor_dev_attr(attr); - struct s3c_hwmon_pdata *pdata = dev->platform_data; - struct s3c_hwmon_chcfg *cfg; - - cfg = pdata->in[sen_attr->index]; - - return snprintf(buf, PAGE_SIZE, "%s\n", cfg->name); -} - -/** - * s3c_hwmon_create_attr - create hwmon attribute for given channel. - * @dev: The device to create the attribute on. - * @cfg: The channel configuration passed from the platform data. - * @channel: The ADC channel number to process. - * - * Create the scaled attribute for use with hwmon from the specified - * platform data in @pdata. The sysfs entry is handled by the routine - * s3c_hwmon_ch_show(). - * - * The attribute name is taken from the configuration data if present - * otherwise the name is taken by concatenating in_ with the channel - * number. - */ -static int s3c_hwmon_create_attr(struct device *dev, - struct s3c_hwmon_chcfg *cfg, - struct s3c_hwmon_attr *attrs, - int channel) -{ - struct sensor_device_attribute *attr; - int ret; - - snprintf(attrs->in_name, sizeof(attrs->in_name), "in%d_input", channel); - - attr = &attrs->in; - attr->index = channel; - sysfs_attr_init(&attr->dev_attr.attr); - attr->dev_attr.attr.name = attrs->in_name; - attr->dev_attr.attr.mode = S_IRUGO; - attr->dev_attr.show = s3c_hwmon_ch_show; - - ret = device_create_file(dev, &attr->dev_attr); - if (ret < 0) { - dev_err(dev, "failed to create input attribute\n"); - return ret; - } - - /* if this has a name, add a label */ - if (cfg->name) { - snprintf(attrs->label_name, sizeof(attrs->label_name), - "in%d_label", channel); - - attr = &attrs->label; - attr->index = channel; - sysfs_attr_init(&attr->dev_attr.attr); - attr->dev_attr.attr.name = attrs->label_name; - attr->dev_attr.attr.mode = S_IRUGO; - attr->dev_attr.show = s3c_hwmon_label_show; - - ret = device_create_file(dev, &attr->dev_attr); - if (ret < 0) { - device_remove_file(dev, &attrs->in.dev_attr); - dev_err(dev, "failed to create label attribute\n"); - } - } - - return ret; -} - -static void s3c_hwmon_remove_attr(struct device *dev, - struct s3c_hwmon_attr *attrs) -{ - device_remove_file(dev, &attrs->in.dev_attr); - device_remove_file(dev, &attrs->label.dev_attr); -} - -/** - * s3c_hwmon_probe - device probe entry. - * @dev: The device being probed. -*/ -static int __devinit s3c_hwmon_probe(struct platform_device *dev) -{ - struct s3c_hwmon_pdata *pdata = dev->dev.platform_data; - struct s3c_hwmon *hwmon; - int ret = 0; - int i; - - if (!pdata) { - dev_err(&dev->dev, "no platform data supplied\n"); - return -EINVAL; - } - - hwmon = kzalloc(sizeof(struct s3c_hwmon), GFP_KERNEL); - if (hwmon == NULL) { - dev_err(&dev->dev, "no memory\n"); - return -ENOMEM; - } - - platform_set_drvdata(dev, hwmon); - - mutex_init(&hwmon->lock); - - /* Register with the core ADC driver. */ - - hwmon->client = s3c_adc_register(dev, NULL, NULL, 0); - if (IS_ERR(hwmon->client)) { - dev_err(&dev->dev, "cannot register adc\n"); - ret = PTR_ERR(hwmon->client); - goto err_mem; - } - - /* add attributes for our adc devices. */ - - ret = s3c_hwmon_add_raw(&dev->dev); - if (ret) - goto err_registered; - - /* register with the hwmon core */ - - hwmon->hwmon_dev = hwmon_device_register(&dev->dev); - if (IS_ERR(hwmon->hwmon_dev)) { - dev_err(&dev->dev, "error registering with hwmon\n"); - ret = PTR_ERR(hwmon->hwmon_dev); - goto err_raw_attribute; - } - - for (i = 0; i < ARRAY_SIZE(pdata->in); i++) { - struct s3c_hwmon_chcfg *cfg = pdata->in[i]; - - if (!cfg) - continue; - - if (cfg->mult >= 0x10000) - dev_warn(&dev->dev, - "channel %d multiplier too large\n", - i); - - if (cfg->div == 0) { - dev_err(&dev->dev, "channel %d divider zero\n", i); - continue; - } - - ret = s3c_hwmon_create_attr(&dev->dev, pdata->in[i], - &hwmon->attrs[i], i); - if (ret) { - dev_err(&dev->dev, - "error creating channel %d\n", i); - - for (i--; i >= 0; i--) - s3c_hwmon_remove_attr(&dev->dev, - &hwmon->attrs[i]); - - goto err_hwmon_register; - } - } - - return 0; - - err_hwmon_register: - hwmon_device_unregister(hwmon->hwmon_dev); - - err_raw_attribute: - s3c_hwmon_remove_raw(&dev->dev); - - err_registered: - s3c_adc_release(hwmon->client); - - err_mem: - kfree(hwmon); - return ret; -} - -static int __devexit s3c_hwmon_remove(struct platform_device *dev) -{ - struct s3c_hwmon *hwmon = platform_get_drvdata(dev); - int i; - - s3c_hwmon_remove_raw(&dev->dev); - - for (i = 0; i < ARRAY_SIZE(hwmon->attrs); i++) - s3c_hwmon_remove_attr(&dev->dev, &hwmon->attrs[i]); - - hwmon_device_unregister(hwmon->hwmon_dev); - s3c_adc_release(hwmon->client); - - return 0; -} - -static struct platform_driver s3c_hwmon_driver = { - .driver = { - .name = "s3c-hwmon", - .owner = THIS_MODULE, - }, - .probe = s3c_hwmon_probe, - .remove = __devexit_p(s3c_hwmon_remove), -}; - -module_platform_driver(s3c_hwmon_driver); - -MODULE_AUTHOR("Ben Dooks "); -MODULE_DESCRIPTION("S3C ADC HWMon driver"); -MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("platform:s3c-hwmon"); diff --git a/ANDROID_3.4.5/drivers/hwmon/sch5627.c b/ANDROID_3.4.5/drivers/hwmon/sch5627.c deleted file mode 100644 index 8ec6dfbc..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sch5627.c +++ /dev/null @@ -1,606 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 Hans de Goede * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sch56xx-common.h" - -#define DRVNAME "sch5627" -#define DEVNAME DRVNAME /* We only support one model */ - -#define SCH5627_HWMON_ID 0xa5 -#define SCH5627_COMPANY_ID 0x5c -#define SCH5627_PRIMARY_ID 0xa0 - -#define SCH5627_REG_BUILD_CODE 0x39 -#define SCH5627_REG_BUILD_ID 0x3a -#define SCH5627_REG_HWMON_ID 0x3c -#define SCH5627_REG_HWMON_REV 0x3d -#define SCH5627_REG_COMPANY_ID 0x3e -#define SCH5627_REG_PRIMARY_ID 0x3f -#define SCH5627_REG_CTRL 0x40 - -#define SCH5627_NO_TEMPS 8 -#define SCH5627_NO_FANS 4 -#define SCH5627_NO_IN 5 - -static const u16 SCH5627_REG_TEMP_MSB[SCH5627_NO_TEMPS] = { - 0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181 }; -static const u16 SCH5627_REG_TEMP_LSN[SCH5627_NO_TEMPS] = { - 0xE2, 0xE1, 0xE1, 0xE5, 0xE5, 0xE6, 0x182, 0x182 }; -static const u16 SCH5627_REG_TEMP_HIGH_NIBBLE[SCH5627_NO_TEMPS] = { - 0, 0, 1, 1, 0, 0, 0, 1 }; -static const u16 SCH5627_REG_TEMP_HIGH[SCH5627_NO_TEMPS] = { - 0x61, 0x57, 0x59, 0x5B, 0x5D, 0x5F, 0x184, 0x186 }; -static const u16 SCH5627_REG_TEMP_ABS[SCH5627_NO_TEMPS] = { - 0x9B, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x1A8, 0x1A9 }; - -static const u16 SCH5627_REG_FAN[SCH5627_NO_FANS] = { - 0x2C, 0x2E, 0x30, 0x32 }; -static const u16 SCH5627_REG_FAN_MIN[SCH5627_NO_FANS] = { - 0x62, 0x64, 0x66, 0x68 }; - -static const u16 SCH5627_REG_IN_MSB[SCH5627_NO_IN] = { - 0x22, 0x23, 0x24, 0x25, 0x189 }; -static const u16 SCH5627_REG_IN_LSN[SCH5627_NO_IN] = { - 0xE4, 0xE4, 0xE3, 0xE3, 0x18A }; -static const u16 SCH5627_REG_IN_HIGH_NIBBLE[SCH5627_NO_IN] = { - 1, 0, 1, 0, 1 }; -static const u16 SCH5627_REG_IN_FACTOR[SCH5627_NO_IN] = { - 10745, 3660, 9765, 10745, 3660 }; -static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = { - "VCC", "VTT", "VBAT", "VTR", "V_IN" }; - -struct sch5627_data { - unsigned short addr; - struct device *hwmon_dev; - struct sch56xx_watchdog_data *watchdog; - u8 control; - u8 temp_max[SCH5627_NO_TEMPS]; - u8 temp_crit[SCH5627_NO_TEMPS]; - u16 fan_min[SCH5627_NO_FANS]; - - struct mutex update_lock; - unsigned long last_battery; /* In jiffies */ - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - u16 temp[SCH5627_NO_TEMPS]; - u16 fan[SCH5627_NO_FANS]; - u16 in[SCH5627_NO_IN]; -}; - -static struct sch5627_data *sch5627_update_device(struct device *dev) -{ - struct sch5627_data *data = dev_get_drvdata(dev); - struct sch5627_data *ret = data; - int i, val; - - mutex_lock(&data->update_lock); - - /* Trigger a Vbat voltage measurement every 5 minutes */ - if (time_after(jiffies, data->last_battery + 300 * HZ)) { - sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL, - data->control | 0x10); - data->last_battery = jiffies; - } - - /* Cache the values for 1 second */ - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - for (i = 0; i < SCH5627_NO_TEMPS; i++) { - val = sch56xx_read_virtual_reg12(data->addr, - SCH5627_REG_TEMP_MSB[i], - SCH5627_REG_TEMP_LSN[i], - SCH5627_REG_TEMP_HIGH_NIBBLE[i]); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->temp[i] = val; - } - - for (i = 0; i < SCH5627_NO_FANS; i++) { - val = sch56xx_read_virtual_reg16(data->addr, - SCH5627_REG_FAN[i]); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->fan[i] = val; - } - - for (i = 0; i < SCH5627_NO_IN; i++) { - val = sch56xx_read_virtual_reg12(data->addr, - SCH5627_REG_IN_MSB[i], - SCH5627_REG_IN_LSN[i], - SCH5627_REG_IN_HIGH_NIBBLE[i]); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->in[i] = val; - } - - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -static int __devinit sch5627_read_limits(struct sch5627_data *data) -{ - int i, val; - - for (i = 0; i < SCH5627_NO_TEMPS; i++) { - /* - * Note what SMSC calls ABS, is what lm_sensors calls max - * (aka high), and HIGH is what lm_sensors calls crit. - */ - val = sch56xx_read_virtual_reg(data->addr, - SCH5627_REG_TEMP_ABS[i]); - if (val < 0) - return val; - data->temp_max[i] = val; - - val = sch56xx_read_virtual_reg(data->addr, - SCH5627_REG_TEMP_HIGH[i]); - if (val < 0) - return val; - data->temp_crit[i] = val; - } - for (i = 0; i < SCH5627_NO_FANS; i++) { - val = sch56xx_read_virtual_reg16(data->addr, - SCH5627_REG_FAN_MIN[i]); - if (val < 0) - return val; - data->fan_min[i] = val; - } - - return 0; -} - -static int reg_to_temp(u16 reg) -{ - return (reg * 625) / 10 - 64000; -} - -static int reg_to_temp_limit(u8 reg) -{ - return (reg - 64) * 1000; -} - -static int reg_to_rpm(u16 reg) -{ - if (reg == 0) - return -EIO; - if (reg == 0xffff) - return 0; - - return 5400540 / reg; -} - -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME); -} - -static ssize_t show_temp(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = sch5627_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = reg_to_temp(data->temp[attr->index]); - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = sch5627_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = dev_get_drvdata(dev); - int val; - - val = reg_to_temp_limit(data->temp_max[attr->index]); - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_temp_crit(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = dev_get_drvdata(dev); - int val; - - val = reg_to_temp_limit(data->temp_crit[attr->index]); - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_fan(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = sch5627_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = reg_to_rpm(data->fan[attr->index]); - if (val < 0) - return val; - - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_fan_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = sch5627_update_device(dev); - - if (IS_ERR(data)) - return PTR_ERR(data); - - return snprintf(buf, PAGE_SIZE, "%d\n", - data->fan[attr->index] == 0xffff); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = dev_get_drvdata(dev); - int val = reg_to_rpm(data->fan_min[attr->index]); - if (val < 0) - return val; - - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_in(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5627_data *data = sch5627_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = DIV_ROUND_CLOSEST( - data->in[attr->index] * SCH5627_REG_IN_FACTOR[attr->index], - 10000); - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_in_label(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - - return snprintf(buf, PAGE_SIZE, "%s\n", - SCH5627_IN_LABELS[attr->index]); -} - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3); -static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4); -static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5); -static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6); -static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7); - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3); - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); -static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3); - -static struct attribute *sch5627_attributes[] = { - &dev_attr_name.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp7_input.dev_attr.attr, - &sensor_dev_attr_temp8_input.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp4_fault.dev_attr.attr, - &sensor_dev_attr_temp5_fault.dev_attr.attr, - &sensor_dev_attr_temp6_fault.dev_attr.attr, - &sensor_dev_attr_temp7_fault.dev_attr.attr, - &sensor_dev_attr_temp8_fault.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp5_max.dev_attr.attr, - &sensor_dev_attr_temp6_max.dev_attr.attr, - &sensor_dev_attr_temp7_max.dev_attr.attr, - &sensor_dev_attr_temp8_max.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp4_crit.dev_attr.attr, - &sensor_dev_attr_temp5_crit.dev_attr.attr, - &sensor_dev_attr_temp6_crit.dev_attr.attr, - &sensor_dev_attr_temp7_crit.dev_attr.attr, - &sensor_dev_attr_temp8_crit.dev_attr.attr, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - &sensor_dev_attr_fan2_fault.dev_attr.attr, - &sensor_dev_attr_fan3_fault.dev_attr.attr, - &sensor_dev_attr_fan4_fault.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in0_label.dev_attr.attr, - &sensor_dev_attr_in1_label.dev_attr.attr, - &sensor_dev_attr_in2_label.dev_attr.attr, - &sensor_dev_attr_in3_label.dev_attr.attr, - /* No in4_label as in4 is a generic input pin */ - - NULL -}; - -static const struct attribute_group sch5627_group = { - .attrs = sch5627_attributes, -}; - -static int sch5627_remove(struct platform_device *pdev) -{ - struct sch5627_data *data = platform_get_drvdata(pdev); - - if (data->watchdog) - sch56xx_watchdog_unregister(data->watchdog); - - if (data->hwmon_dev) - hwmon_device_unregister(data->hwmon_dev); - - sysfs_remove_group(&pdev->dev.kobj, &sch5627_group); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static int __devinit sch5627_probe(struct platform_device *pdev) -{ - struct sch5627_data *data; - int err, build_code, build_id, hwmon_rev, val; - - data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_HWMON_ID); - if (val < 0) { - err = val; - goto error; - } - if (val != SCH5627_HWMON_ID) { - pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "hwmon", - val, SCH5627_HWMON_ID); - err = -ENODEV; - goto error; - } - - val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_COMPANY_ID); - if (val < 0) { - err = val; - goto error; - } - if (val != SCH5627_COMPANY_ID) { - pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "company", - val, SCH5627_COMPANY_ID); - err = -ENODEV; - goto error; - } - - val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_PRIMARY_ID); - if (val < 0) { - err = val; - goto error; - } - if (val != SCH5627_PRIMARY_ID) { - pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "primary", - val, SCH5627_PRIMARY_ID); - err = -ENODEV; - goto error; - } - - build_code = sch56xx_read_virtual_reg(data->addr, - SCH5627_REG_BUILD_CODE); - if (build_code < 0) { - err = build_code; - goto error; - } - - build_id = sch56xx_read_virtual_reg16(data->addr, - SCH5627_REG_BUILD_ID); - if (build_id < 0) { - err = build_id; - goto error; - } - - hwmon_rev = sch56xx_read_virtual_reg(data->addr, - SCH5627_REG_HWMON_REV); - if (hwmon_rev < 0) { - err = hwmon_rev; - goto error; - } - - val = sch56xx_read_virtual_reg(data->addr, SCH5627_REG_CTRL); - if (val < 0) { - err = val; - goto error; - } - data->control = val; - if (!(data->control & 0x01)) { - pr_err("hardware monitoring not enabled\n"); - err = -ENODEV; - goto error; - } - /* Trigger a Vbat voltage measurement, so that we get a valid reading - the first time we read Vbat */ - sch56xx_write_virtual_reg(data->addr, SCH5627_REG_CTRL, - data->control | 0x10); - data->last_battery = jiffies; - - /* - * Read limits, we do this only once as reading a register on - * the sch5627 is quite expensive (and they don't change). - */ - err = sch5627_read_limits(data); - if (err) - goto error; - - pr_info("found %s chip at %#hx\n", DEVNAME, data->addr); - pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n", - build_code, build_id, hwmon_rev); - - /* Register sysfs interface files */ - err = sysfs_create_group(&pdev->dev.kobj, &sch5627_group); - if (err) - goto error; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - data->hwmon_dev = NULL; - goto error; - } - - /* Note failing to register the watchdog is not a fatal error */ - data->watchdog = sch56xx_watchdog_register(data->addr, - (build_code << 24) | (build_id << 8) | hwmon_rev, - &data->update_lock, 1); - - return 0; - -error: - sch5627_remove(pdev); - return err; -} - -static struct platform_driver sch5627_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = sch5627_probe, - .remove = sch5627_remove, -}; - -module_platform_driver(sch5627_driver); - -MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver"); -MODULE_AUTHOR("Hans de Goede "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/sch5636.c b/ANDROID_3.4.5/drivers/hwmon/sch5636.c deleted file mode 100644 index 906d4ed3..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sch5636.c +++ /dev/null @@ -1,537 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2011-2012 Hans de Goede * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sch56xx-common.h" - -#define DRVNAME "sch5636" -#define DEVNAME "theseus" /* We only support one model for now */ - -#define SCH5636_REG_FUJITSU_ID 0x780 -#define SCH5636_REG_FUJITSU_REV 0x783 - -#define SCH5636_NO_INS 5 -#define SCH5636_NO_TEMPS 16 -#define SCH5636_NO_FANS 8 - -static const u16 SCH5636_REG_IN_VAL[SCH5636_NO_INS] = { - 0x22, 0x23, 0x24, 0x25, 0x189 }; -static const u16 SCH5636_REG_IN_FACTORS[SCH5636_NO_INS] = { - 4400, 1500, 4000, 4400, 16000 }; -static const char * const SCH5636_IN_LABELS[SCH5636_NO_INS] = { - "3.3V", "VREF", "VBAT", "3.3AUX", "12V" }; - -static const u16 SCH5636_REG_TEMP_VAL[SCH5636_NO_TEMPS] = { - 0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181, - 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C }; -#define SCH5636_REG_TEMP_CTRL(i) (0x790 + (i)) -#define SCH5636_TEMP_WORKING 0x01 -#define SCH5636_TEMP_ALARM 0x02 -#define SCH5636_TEMP_DEACTIVATED 0x80 - -static const u16 SCH5636_REG_FAN_VAL[SCH5636_NO_FANS] = { - 0x2C, 0x2E, 0x30, 0x32, 0x62, 0x64, 0x66, 0x68 }; -#define SCH5636_REG_FAN_CTRL(i) (0x880 + (i)) -/* FAULT in datasheet, but acts as an alarm */ -#define SCH5636_FAN_ALARM 0x04 -#define SCH5636_FAN_NOT_PRESENT 0x08 -#define SCH5636_FAN_DEACTIVATED 0x80 - - -struct sch5636_data { - unsigned short addr; - struct device *hwmon_dev; - struct sch56xx_watchdog_data *watchdog; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - u8 in[SCH5636_NO_INS]; - u8 temp_val[SCH5636_NO_TEMPS]; - u8 temp_ctrl[SCH5636_NO_TEMPS]; - u16 fan_val[SCH5636_NO_FANS]; - u8 fan_ctrl[SCH5636_NO_FANS]; -}; - -static struct sch5636_data *sch5636_update_device(struct device *dev) -{ - struct sch5636_data *data = dev_get_drvdata(dev); - struct sch5636_data *ret = data; - int i, val; - - mutex_lock(&data->update_lock); - - /* Cache the values for 1 second */ - if (data->valid && !time_after(jiffies, data->last_updated + HZ)) - goto abort; - - for (i = 0; i < SCH5636_NO_INS; i++) { - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_IN_VAL[i]); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->in[i] = val; - } - - for (i = 0; i < SCH5636_NO_TEMPS; i++) { - if (data->temp_ctrl[i] & SCH5636_TEMP_DEACTIVATED) - continue; - - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_TEMP_VAL[i]); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_val[i] = val; - - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_TEMP_CTRL(i)); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->temp_ctrl[i] = val; - /* Alarms need to be explicitly write-cleared */ - if (val & SCH5636_TEMP_ALARM) { - sch56xx_write_virtual_reg(data->addr, - SCH5636_REG_TEMP_CTRL(i), val); - } - } - - for (i = 0; i < SCH5636_NO_FANS; i++) { - if (data->fan_ctrl[i] & SCH5636_FAN_DEACTIVATED) - continue; - - val = sch56xx_read_virtual_reg16(data->addr, - SCH5636_REG_FAN_VAL[i]); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->fan_val[i] = val; - - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_FAN_CTRL(i)); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->fan_ctrl[i] = val; - /* Alarms need to be explicitly write-cleared */ - if (val & SCH5636_FAN_ALARM) { - sch56xx_write_virtual_reg(data->addr, - SCH5636_REG_FAN_CTRL(i), val); - } - } - - data->last_updated = jiffies; - data->valid = 1; -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -static int reg_to_rpm(u16 reg) -{ - if (reg == 0) - return -EIO; - if (reg == 0xffff) - return 0; - - return 5400540 / reg; -} - -static ssize_t show_name(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME); -} - -static ssize_t show_in_value(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = DIV_ROUND_CLOSEST( - data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index], - 255); - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_in_label(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - - return snprintf(buf, PAGE_SIZE, "%s\n", - SCH5636_IN_LABELS[attr->index]); -} - -static ssize_t show_temp_value(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = (data->temp_val[attr->index] - 64) * 1000; - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_temp_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1; - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_temp_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0; - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_fan_value(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = reg_to_rpm(data->fan_val[attr->index]); - if (val < 0) - return val; - - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_fan_fault(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0; - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t show_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct sch5636_data *data = sch5636_update_device(dev); - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0; - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static struct sensor_device_attribute sch5636_attr[] = { - SENSOR_ATTR(name, 0444, show_name, NULL, 0), - SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0), - SENSOR_ATTR(in0_label, 0444, show_in_label, NULL, 0), - SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1), - SENSOR_ATTR(in1_label, 0444, show_in_label, NULL, 1), - SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2), - SENSOR_ATTR(in2_label, 0444, show_in_label, NULL, 2), - SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3), - SENSOR_ATTR(in3_label, 0444, show_in_label, NULL, 3), - SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4), - SENSOR_ATTR(in4_label, 0444, show_in_label, NULL, 4), -}; - -static struct sensor_device_attribute sch5636_temp_attr[] = { - SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0), - SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0), - SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0), - SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1), - SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1), - SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1), - SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2), - SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2), - SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2), - SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3), - SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3), - SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3), - SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4), - SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4), - SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4), - SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5), - SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5), - SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5), - SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6), - SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6), - SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6), - SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7), - SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7), - SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7), - SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8), - SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8), - SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8), - SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9), - SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9), - SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9), - SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10), - SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10), - SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10), - SENSOR_ATTR(temp12_input, 0444, show_temp_value, NULL, 11), - SENSOR_ATTR(temp12_fault, 0444, show_temp_fault, NULL, 11), - SENSOR_ATTR(temp12_alarm, 0444, show_temp_alarm, NULL, 11), - SENSOR_ATTR(temp13_input, 0444, show_temp_value, NULL, 12), - SENSOR_ATTR(temp13_fault, 0444, show_temp_fault, NULL, 12), - SENSOR_ATTR(temp13_alarm, 0444, show_temp_alarm, NULL, 12), - SENSOR_ATTR(temp14_input, 0444, show_temp_value, NULL, 13), - SENSOR_ATTR(temp14_fault, 0444, show_temp_fault, NULL, 13), - SENSOR_ATTR(temp14_alarm, 0444, show_temp_alarm, NULL, 13), - SENSOR_ATTR(temp15_input, 0444, show_temp_value, NULL, 14), - SENSOR_ATTR(temp15_fault, 0444, show_temp_fault, NULL, 14), - SENSOR_ATTR(temp15_alarm, 0444, show_temp_alarm, NULL, 14), - SENSOR_ATTR(temp16_input, 0444, show_temp_value, NULL, 15), - SENSOR_ATTR(temp16_fault, 0444, show_temp_fault, NULL, 15), - SENSOR_ATTR(temp16_alarm, 0444, show_temp_alarm, NULL, 15), -}; - -static struct sensor_device_attribute sch5636_fan_attr[] = { - SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0), - SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0), - SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0), - SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1), - SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1), - SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1), - SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2), - SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2), - SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2), - SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3), - SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3), - SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3), - SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4), - SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4), - SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4), - SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5), - SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5), - SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5), - SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6), - SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6), - SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6), - SENSOR_ATTR(fan8_input, 0444, show_fan_value, NULL, 7), - SENSOR_ATTR(fan8_fault, 0444, show_fan_fault, NULL, 7), - SENSOR_ATTR(fan8_alarm, 0444, show_fan_alarm, NULL, 7), -}; - -static int sch5636_remove(struct platform_device *pdev) -{ - struct sch5636_data *data = platform_get_drvdata(pdev); - int i; - - if (data->watchdog) - sch56xx_watchdog_unregister(data->watchdog); - - if (data->hwmon_dev) - hwmon_device_unregister(data->hwmon_dev); - - for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) - device_remove_file(&pdev->dev, &sch5636_attr[i].dev_attr); - - for (i = 0; i < SCH5636_NO_TEMPS * 3; i++) - device_remove_file(&pdev->dev, - &sch5636_temp_attr[i].dev_attr); - - for (i = 0; i < SCH5636_NO_FANS * 3; i++) - device_remove_file(&pdev->dev, - &sch5636_fan_attr[i].dev_attr); - - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static int __devinit sch5636_probe(struct platform_device *pdev) -{ - struct sch5636_data *data; - int i, err, val, revision[2]; - char id[4]; - - data = kzalloc(sizeof(struct sch5636_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start; - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - for (i = 0; i < 3; i++) { - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_FUJITSU_ID + i); - if (val < 0) { - pr_err("Could not read Fujitsu id byte at %#x\n", - SCH5636_REG_FUJITSU_ID + i); - err = val; - goto error; - } - id[i] = val; - } - id[i] = '\0'; - - if (strcmp(id, "THS")) { - pr_err("Unknown Fujitsu id: %02x%02x%02x\n", - id[0], id[1], id[2]); - err = -ENODEV; - goto error; - } - - for (i = 0; i < 2; i++) { - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_FUJITSU_REV + i); - if (val < 0) { - err = val; - goto error; - } - revision[i] = val; - } - pr_info("Found %s chip at %#hx, revison: %d.%02d\n", DEVNAME, - data->addr, revision[0], revision[1]); - - /* Read all temp + fan ctrl registers to determine which are active */ - for (i = 0; i < SCH5636_NO_TEMPS; i++) { - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_TEMP_CTRL(i)); - if (unlikely(val < 0)) { - err = val; - goto error; - } - data->temp_ctrl[i] = val; - } - - for (i = 0; i < SCH5636_NO_FANS; i++) { - val = sch56xx_read_virtual_reg(data->addr, - SCH5636_REG_FAN_CTRL(i)); - if (unlikely(val < 0)) { - err = val; - goto error; - } - data->fan_ctrl[i] = val; - } - - for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) { - err = device_create_file(&pdev->dev, - &sch5636_attr[i].dev_attr); - if (err) - goto error; - } - - for (i = 0; i < (SCH5636_NO_TEMPS * 3); i++) { - if (data->temp_ctrl[i/3] & SCH5636_TEMP_DEACTIVATED) - continue; - - err = device_create_file(&pdev->dev, - &sch5636_temp_attr[i].dev_attr); - if (err) - goto error; - } - - for (i = 0; i < (SCH5636_NO_FANS * 3); i++) { - if (data->fan_ctrl[i/3] & SCH5636_FAN_DEACTIVATED) - continue; - - err = device_create_file(&pdev->dev, - &sch5636_fan_attr[i].dev_attr); - if (err) - goto error; - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - data->hwmon_dev = NULL; - goto error; - } - - /* Note failing to register the watchdog is not a fatal error */ - data->watchdog = sch56xx_watchdog_register(data->addr, - (revision[0] << 8) | revision[1], - &data->update_lock, 0); - - return 0; - -error: - sch5636_remove(pdev); - return err; -} - -static struct platform_driver sch5636_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = sch5636_probe, - .remove = sch5636_remove, -}; - -module_platform_driver(sch5636_driver); - -MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver"); -MODULE_AUTHOR("Hans de Goede "); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/sch56xx-common.c b/ANDROID_3.4.5/drivers/hwmon/sch56xx-common.c deleted file mode 100644 index ce52fc57..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sch56xx-common.c +++ /dev/null @@ -1,855 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 Hans de Goede * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "sch56xx-common.h" - -/* Insmod parameters */ -static int nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, int, 0); -MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -#define SIO_SCH56XX_LD_EM 0x0C /* Embedded uController Logical Dev */ -#define SIO_UNLOCK_KEY 0x55 /* Key to enable Super-I/O */ -#define SIO_LOCK_KEY 0xAA /* Key to disable Super-I/O */ - -#define SIO_REG_LDSEL 0x07 /* Logical device select */ -#define SIO_REG_DEVID 0x20 /* Device ID */ -#define SIO_REG_ENABLE 0x30 /* Logical device enable */ -#define SIO_REG_ADDR 0x66 /* Logical device address (2 bytes) */ - -#define SIO_SCH5627_ID 0xC6 /* Chipset ID */ -#define SIO_SCH5636_ID 0xC7 /* Chipset ID */ - -#define REGION_LENGTH 10 - -#define SCH56XX_CMD_READ 0x02 -#define SCH56XX_CMD_WRITE 0x03 - -/* Watchdog registers */ -#define SCH56XX_REG_WDOG_PRESET 0x58B -#define SCH56XX_REG_WDOG_CONTROL 0x58C -#define SCH56XX_WDOG_TIME_BASE_SEC 0x01 -#define SCH56XX_REG_WDOG_OUTPUT_ENABLE 0x58E -#define SCH56XX_WDOG_OUTPUT_ENABLE 0x02 - -struct sch56xx_watchdog_data { - u16 addr; - u32 revision; - struct mutex *io_lock; - struct mutex watchdog_lock; - struct list_head list; /* member of the watchdog_data_list */ - struct kref kref; - struct miscdevice watchdog_miscdev; - unsigned long watchdog_is_open; - char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ - char watchdog_expect_close; - u8 watchdog_preset; - u8 watchdog_control; - u8 watchdog_output_enable; -}; - -static struct platform_device *sch56xx_pdev; - -/* - * Somewhat ugly :( global data pointer list with all sch56xx devices, so that - * we can find our device data as when using misc_register there is no other - * method to get to ones device data from the open fop. - */ -static LIST_HEAD(watchdog_data_list); -/* Note this lock not only protect list access, but also data.kref access */ -static DEFINE_MUTEX(watchdog_data_mutex); - -/* Super I/O functions */ -static inline int superio_inb(int base, int reg) -{ - outb(reg, base); - return inb(base + 1); -} - -static inline int superio_enter(int base) -{ - /* Don't step on other drivers' I/O space by accident */ - if (!request_muxed_region(base, 2, "sch56xx")) { - pr_err("I/O address 0x%04x already in use\n", base); - return -EBUSY; - } - - outb(SIO_UNLOCK_KEY, base); - - return 0; -} - -static inline void superio_select(int base, int ld) -{ - outb(SIO_REG_LDSEL, base); - outb(ld, base + 1); -} - -static inline void superio_exit(int base) -{ - outb(SIO_LOCK_KEY, base); - release_region(base, 2); -} - -static int sch56xx_send_cmd(u16 addr, u8 cmd, u16 reg, u8 v) -{ - u8 val; - int i; - /* - * According to SMSC for the commands we use the maximum time for - * the EM to respond is 15 ms, but testing shows in practice it - * responds within 15-32 reads, so we first busy poll, and if - * that fails sleep a bit and try again until we are way past - * the 15 ms maximum response time. - */ - const int max_busy_polls = 64; - const int max_lazy_polls = 32; - - /* (Optional) Write-Clear the EC to Host Mailbox Register */ - val = inb(addr + 1); - outb(val, addr + 1); - - /* Set Mailbox Address Pointer to first location in Region 1 */ - outb(0x00, addr + 2); - outb(0x80, addr + 3); - - /* Write Request Packet Header */ - outb(cmd, addr + 4); /* VREG Access Type read:0x02 write:0x03 */ - outb(0x01, addr + 5); /* # of Entries: 1 Byte (8-bit) */ - outb(0x04, addr + 2); /* Mailbox AP to first data entry loc. */ - - /* Write Value field */ - if (cmd == SCH56XX_CMD_WRITE) - outb(v, addr + 4); - - /* Write Address field */ - outb(reg & 0xff, addr + 6); - outb(reg >> 8, addr + 7); - - /* Execute the Random Access Command */ - outb(0x01, addr); /* Write 01h to the Host-to-EC register */ - - /* EM Interface Polling "Algorithm" */ - for (i = 0; i < max_busy_polls + max_lazy_polls; i++) { - if (i >= max_busy_polls) - msleep(1); - /* Read Interrupt source Register */ - val = inb(addr + 8); - /* Write Clear the interrupt source bits */ - if (val) - outb(val, addr + 8); - /* Command Completed ? */ - if (val & 0x01) - break; - } - if (i == max_busy_polls + max_lazy_polls) { - pr_err("Max retries exceeded reading virtual " - "register 0x%04hx (%d)\n", reg, 1); - return -EIO; - } - - /* - * According to SMSC we may need to retry this, but sofar I've always - * seen this succeed in 1 try. - */ - for (i = 0; i < max_busy_polls; i++) { - /* Read EC-to-Host Register */ - val = inb(addr + 1); - /* Command Completed ? */ - if (val == 0x01) - break; - - if (i == 0) - pr_warn("EC reports: 0x%02x reading virtual register " - "0x%04hx\n", (unsigned int)val, reg); - } - if (i == max_busy_polls) { - pr_err("Max retries exceeded reading virtual " - "register 0x%04hx (%d)\n", reg, 2); - return -EIO; - } - - /* - * According to the SMSC app note we should now do: - * - * Set Mailbox Address Pointer to first location in Region 1 * - * outb(0x00, addr + 2); - * outb(0x80, addr + 3); - * - * But if we do that things don't work, so let's not. - */ - - /* Read Value field */ - if (cmd == SCH56XX_CMD_READ) - return inb(addr + 4); - - return 0; -} - -int sch56xx_read_virtual_reg(u16 addr, u16 reg) -{ - return sch56xx_send_cmd(addr, SCH56XX_CMD_READ, reg, 0); -} -EXPORT_SYMBOL(sch56xx_read_virtual_reg); - -int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val) -{ - return sch56xx_send_cmd(addr, SCH56XX_CMD_WRITE, reg, val); -} -EXPORT_SYMBOL(sch56xx_write_virtual_reg); - -int sch56xx_read_virtual_reg16(u16 addr, u16 reg) -{ - int lsb, msb; - - /* Read LSB first, this will cause the matching MSB to be latched */ - lsb = sch56xx_read_virtual_reg(addr, reg); - if (lsb < 0) - return lsb; - - msb = sch56xx_read_virtual_reg(addr, reg + 1); - if (msb < 0) - return msb; - - return lsb | (msb << 8); -} -EXPORT_SYMBOL(sch56xx_read_virtual_reg16); - -int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg, - int high_nibble) -{ - int msb, lsn; - - /* Read MSB first, this will cause the matching LSN to be latched */ - msb = sch56xx_read_virtual_reg(addr, msb_reg); - if (msb < 0) - return msb; - - lsn = sch56xx_read_virtual_reg(addr, lsn_reg); - if (lsn < 0) - return lsn; - - if (high_nibble) - return (msb << 4) | (lsn >> 4); - else - return (msb << 4) | (lsn & 0x0f); -} -EXPORT_SYMBOL(sch56xx_read_virtual_reg12); - -/* - * Watchdog routines - */ - -/* - * Release our data struct when the platform device has been released *and* - * all references to our watchdog device are released. - */ -static void sch56xx_watchdog_release_resources(struct kref *r) -{ - struct sch56xx_watchdog_data *data = - container_of(r, struct sch56xx_watchdog_data, kref); - kfree(data); -} - -static int watchdog_set_timeout(struct sch56xx_watchdog_data *data, - int timeout) -{ - int ret, resolution; - u8 control; - - /* 1 second or 60 second resolution? */ - if (timeout <= 255) - resolution = 1; - else - resolution = 60; - - if (timeout < resolution || timeout > (resolution * 255)) - return -EINVAL; - - mutex_lock(&data->watchdog_lock); - if (!data->addr) { - ret = -ENODEV; - goto leave; - } - - if (resolution == 1) - control = data->watchdog_control | SCH56XX_WDOG_TIME_BASE_SEC; - else - control = data->watchdog_control & ~SCH56XX_WDOG_TIME_BASE_SEC; - - if (data->watchdog_control != control) { - mutex_lock(data->io_lock); - ret = sch56xx_write_virtual_reg(data->addr, - SCH56XX_REG_WDOG_CONTROL, - control); - mutex_unlock(data->io_lock); - if (ret) - goto leave; - - data->watchdog_control = control; - } - - /* - * Remember new timeout value, but do not write as that (re)starts - * the watchdog countdown. - */ - data->watchdog_preset = DIV_ROUND_UP(timeout, resolution); - - ret = data->watchdog_preset * resolution; -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_get_timeout(struct sch56xx_watchdog_data *data) -{ - int timeout; - - mutex_lock(&data->watchdog_lock); - if (data->watchdog_control & SCH56XX_WDOG_TIME_BASE_SEC) - timeout = data->watchdog_preset; - else - timeout = data->watchdog_preset * 60; - mutex_unlock(&data->watchdog_lock); - - return timeout; -} - -static int watchdog_start(struct sch56xx_watchdog_data *data) -{ - int ret; - u8 val; - - mutex_lock(&data->watchdog_lock); - if (!data->addr) { - ret = -ENODEV; - goto leave_unlock_watchdog; - } - - /* - * The sch56xx's watchdog cannot really be started / stopped - * it is always running, but we can avoid the timer expiring - * from causing a system reset by clearing the output enable bit. - * - * The sch56xx's watchdog will set the watchdog event bit, bit 0 - * of the second interrupt source register (at base-address + 9), - * when the timer expires. - * - * This will only cause a system reset if the 0-1 flank happens when - * output enable is true. Setting output enable after the flank will - * not cause a reset, nor will the timer expiring a second time. - * This means we must clear the watchdog event bit in case it is set. - * - * The timer may still be running (after a recent watchdog_stop) and - * mere milliseconds away from expiring, so the timer must be reset - * first! - */ - - mutex_lock(data->io_lock); - - /* 1. Reset the watchdog countdown counter */ - ret = sch56xx_write_virtual_reg(data->addr, SCH56XX_REG_WDOG_PRESET, - data->watchdog_preset); - if (ret) - goto leave; - - /* 2. Enable output (if not already enabled) */ - if (!(data->watchdog_output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)) { - val = data->watchdog_output_enable | - SCH56XX_WDOG_OUTPUT_ENABLE; - ret = sch56xx_write_virtual_reg(data->addr, - SCH56XX_REG_WDOG_OUTPUT_ENABLE, - val); - if (ret) - goto leave; - - data->watchdog_output_enable = val; - } - - /* 3. Clear the watchdog event bit if set */ - val = inb(data->addr + 9); - if (val & 0x01) - outb(0x01, data->addr + 9); - -leave: - mutex_unlock(data->io_lock); -leave_unlock_watchdog: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_trigger(struct sch56xx_watchdog_data *data) -{ - int ret; - - mutex_lock(&data->watchdog_lock); - if (!data->addr) { - ret = -ENODEV; - goto leave; - } - - /* Reset the watchdog countdown counter */ - mutex_lock(data->io_lock); - ret = sch56xx_write_virtual_reg(data->addr, SCH56XX_REG_WDOG_PRESET, - data->watchdog_preset); - mutex_unlock(data->io_lock); -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_stop_unlocked(struct sch56xx_watchdog_data *data) -{ - int ret = 0; - u8 val; - - if (!data->addr) - return -ENODEV; - - if (data->watchdog_output_enable & SCH56XX_WDOG_OUTPUT_ENABLE) { - val = data->watchdog_output_enable & - ~SCH56XX_WDOG_OUTPUT_ENABLE; - mutex_lock(data->io_lock); - ret = sch56xx_write_virtual_reg(data->addr, - SCH56XX_REG_WDOG_OUTPUT_ENABLE, - val); - mutex_unlock(data->io_lock); - if (ret) - return ret; - - data->watchdog_output_enable = val; - } - - return ret; -} - -static int watchdog_stop(struct sch56xx_watchdog_data *data) -{ - int ret; - - mutex_lock(&data->watchdog_lock); - ret = watchdog_stop_unlocked(data); - mutex_unlock(&data->watchdog_lock); - - return ret; -} - -static int watchdog_release(struct inode *inode, struct file *filp) -{ - struct sch56xx_watchdog_data *data = filp->private_data; - - if (data->watchdog_expect_close) { - watchdog_stop(data); - data->watchdog_expect_close = 0; - } else { - watchdog_trigger(data); - pr_crit("unexpected close, not stopping watchdog!\n"); - } - - clear_bit(0, &data->watchdog_is_open); - - mutex_lock(&watchdog_data_mutex); - kref_put(&data->kref, sch56xx_watchdog_release_resources); - mutex_unlock(&watchdog_data_mutex); - - return 0; -} - -static int watchdog_open(struct inode *inode, struct file *filp) -{ - struct sch56xx_watchdog_data *pos, *data = NULL; - int ret, watchdog_is_open; - - /* - * We get called from drivers/char/misc.c with misc_mtx hold, and we - * call misc_register() from sch56xx_watchdog_probe() with - * watchdog_data_mutex hold, as misc_register() takes the misc_mtx - * lock, this is a possible deadlock, so we use mutex_trylock here. - */ - if (!mutex_trylock(&watchdog_data_mutex)) - return -ERESTARTSYS; - list_for_each_entry(pos, &watchdog_data_list, list) { - if (pos->watchdog_miscdev.minor == iminor(inode)) { - data = pos; - break; - } - } - /* Note we can never not have found data, so we don't check for this */ - watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open); - if (!watchdog_is_open) - kref_get(&data->kref); - mutex_unlock(&watchdog_data_mutex); - - if (watchdog_is_open) - return -EBUSY; - - filp->private_data = data; - - /* Start the watchdog */ - ret = watchdog_start(data); - if (ret) { - watchdog_release(inode, filp); - return ret; - } - - return nonseekable_open(inode, filp); -} - -static ssize_t watchdog_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) -{ - int ret; - struct sch56xx_watchdog_data *data = filp->private_data; - - if (count) { - if (!nowayout) { - size_t i; - - /* Clear it in case it was set with a previous write */ - data->watchdog_expect_close = 0; - - for (i = 0; i != count; i++) { - char c; - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - data->watchdog_expect_close = 1; - } - } - ret = watchdog_trigger(data); - if (ret) - return ret; - } - return count; -} - -static long watchdog_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, - .identity = "sch56xx watchdog" - }; - int i, ret = 0; - struct sch56xx_watchdog_data *data = filp->private_data; - - switch (cmd) { - case WDIOC_GETSUPPORT: - ident.firmware_version = data->revision; - if (!nowayout) - ident.options |= WDIOF_MAGICCLOSE; - if (copy_to_user((void __user *)arg, &ident, sizeof(ident))) - ret = -EFAULT; - break; - - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - ret = put_user(0, (int __user *)arg); - break; - - case WDIOC_KEEPALIVE: - ret = watchdog_trigger(data); - break; - - case WDIOC_GETTIMEOUT: - i = watchdog_get_timeout(data); - ret = put_user(i, (int __user *)arg); - break; - - case WDIOC_SETTIMEOUT: - if (get_user(i, (int __user *)arg)) { - ret = -EFAULT; - break; - } - ret = watchdog_set_timeout(data, i); - if (ret >= 0) - ret = put_user(ret, (int __user *)arg); - break; - - case WDIOC_SETOPTIONS: - if (get_user(i, (int __user *)arg)) { - ret = -EFAULT; - break; - } - - if (i & WDIOS_DISABLECARD) - ret = watchdog_stop(data); - else if (i & WDIOS_ENABLECARD) - ret = watchdog_trigger(data); - else - ret = -EINVAL; - break; - - default: - ret = -ENOTTY; - } - return ret; -} - -static const struct file_operations watchdog_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .open = watchdog_open, - .release = watchdog_release, - .write = watchdog_write, - .unlocked_ioctl = watchdog_ioctl, -}; - -struct sch56xx_watchdog_data *sch56xx_watchdog_register( - u16 addr, u32 revision, struct mutex *io_lock, int check_enabled) -{ - struct sch56xx_watchdog_data *data; - int i, err, control, output_enable; - const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; - - /* Cache the watchdog registers */ - mutex_lock(io_lock); - control = - sch56xx_read_virtual_reg(addr, SCH56XX_REG_WDOG_CONTROL); - output_enable = - sch56xx_read_virtual_reg(addr, SCH56XX_REG_WDOG_OUTPUT_ENABLE); - mutex_unlock(io_lock); - - if (control < 0) - return NULL; - if (output_enable < 0) - return NULL; - if (check_enabled && !(output_enable & SCH56XX_WDOG_OUTPUT_ENABLE)) { - pr_warn("Watchdog not enabled by BIOS, not registering\n"); - return NULL; - } - - data = kzalloc(sizeof(struct sch56xx_watchdog_data), GFP_KERNEL); - if (!data) - return NULL; - - data->addr = addr; - data->revision = revision; - data->io_lock = io_lock; - data->watchdog_control = control; - data->watchdog_output_enable = output_enable; - mutex_init(&data->watchdog_lock); - INIT_LIST_HEAD(&data->list); - kref_init(&data->kref); - - err = watchdog_set_timeout(data, 60); - if (err < 0) - goto error; - - /* - * We take the data_mutex lock early so that watchdog_open() cannot - * run when misc_register() has completed, but we've not yet added - * our data to the watchdog_data_list. - */ - mutex_lock(&watchdog_data_mutex); - for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) { - /* Register our watchdog part */ - snprintf(data->watchdog_name, sizeof(data->watchdog_name), - "watchdog%c", (i == 0) ? '\0' : ('0' + i)); - data->watchdog_miscdev.name = data->watchdog_name; - data->watchdog_miscdev.fops = &watchdog_fops; - data->watchdog_miscdev.minor = watchdog_minors[i]; - err = misc_register(&data->watchdog_miscdev); - if (err == -EBUSY) - continue; - if (err) - break; - - list_add(&data->list, &watchdog_data_list); - pr_info("Registered /dev/%s chardev major 10, minor: %d\n", - data->watchdog_name, watchdog_minors[i]); - break; - } - mutex_unlock(&watchdog_data_mutex); - - if (err) { - pr_err("Registering watchdog chardev: %d\n", err); - goto error; - } - if (i == ARRAY_SIZE(watchdog_minors)) { - pr_warn("Couldn't register watchdog (no free minor)\n"); - goto error; - } - - return data; - -error: - kfree(data); - return NULL; -} -EXPORT_SYMBOL(sch56xx_watchdog_register); - -void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data) -{ - mutex_lock(&watchdog_data_mutex); - misc_deregister(&data->watchdog_miscdev); - list_del(&data->list); - mutex_unlock(&watchdog_data_mutex); - - mutex_lock(&data->watchdog_lock); - if (data->watchdog_is_open) { - pr_warn("platform device unregistered with watchdog " - "open! Stopping watchdog.\n"); - watchdog_stop_unlocked(data); - } - /* Tell the wdog start/stop/trigger functions our dev is gone */ - data->addr = 0; - data->io_lock = NULL; - mutex_unlock(&data->watchdog_lock); - - mutex_lock(&watchdog_data_mutex); - kref_put(&data->kref, sch56xx_watchdog_release_resources); - mutex_unlock(&watchdog_data_mutex); -} -EXPORT_SYMBOL(sch56xx_watchdog_unregister); - -/* - * platform dev find, add and remove functions - */ - -static int __init sch56xx_find(int sioaddr, unsigned short *address, - const char **name) -{ - u8 devid; - int err; - - err = superio_enter(sioaddr); - if (err) - return err; - - devid = superio_inb(sioaddr, SIO_REG_DEVID); - switch (devid) { - case SIO_SCH5627_ID: - *name = "sch5627"; - break; - case SIO_SCH5636_ID: - *name = "sch5636"; - break; - default: - pr_debug("Unsupported device id: 0x%02x\n", - (unsigned int)devid); - err = -ENODEV; - goto exit; - } - - superio_select(sioaddr, SIO_SCH56XX_LD_EM); - - if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) { - pr_warn("Device not activated\n"); - err = -ENODEV; - goto exit; - } - - /* - * Warning the order of the low / high byte is the other way around - * as on most other superio devices!! - */ - *address = superio_inb(sioaddr, SIO_REG_ADDR) | - superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8; - if (*address == 0) { - pr_warn("Base address not set\n"); - err = -ENODEV; - goto exit; - } - -exit: - superio_exit(sioaddr); - return err; -} - -static int __init sch56xx_device_add(unsigned short address, const char *name) -{ - struct resource res = { - .start = address, - .end = address + REGION_LENGTH - 1, - .flags = IORESOURCE_IO, - }; - int err; - - sch56xx_pdev = platform_device_alloc(name, address); - if (!sch56xx_pdev) - return -ENOMEM; - - res.name = sch56xx_pdev->name; - err = acpi_check_resource_conflict(&res); - if (err) - goto exit_device_put; - - err = platform_device_add_resources(sch56xx_pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed\n"); - goto exit_device_put; - } - - err = platform_device_add(sch56xx_pdev); - if (err) { - pr_err("Device addition failed\n"); - goto exit_device_put; - } - - return 0; - -exit_device_put: - platform_device_put(sch56xx_pdev); - - return err; -} - -static int __init sch56xx_init(void) -{ - int err; - unsigned short address; - const char *name; - - err = sch56xx_find(0x4e, &address, &name); - if (err) - err = sch56xx_find(0x2e, &address, &name); - if (err) - return err; - - return sch56xx_device_add(address, name); -} - -static void __exit sch56xx_exit(void) -{ - platform_device_unregister(sch56xx_pdev); -} - -MODULE_DESCRIPTION("SMSC SCH56xx Hardware Monitoring Common Code"); -MODULE_AUTHOR("Hans de Goede "); -MODULE_LICENSE("GPL"); - -module_init(sch56xx_init); -module_exit(sch56xx_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/sch56xx-common.h b/ANDROID_3.4.5/drivers/hwmon/sch56xx-common.h deleted file mode 100644 index 7475086e..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sch56xx-common.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2010-2012 Hans de Goede * - * * - * 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., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#include - -struct sch56xx_watchdog_data; - -int sch56xx_read_virtual_reg(u16 addr, u16 reg); -int sch56xx_write_virtual_reg(u16 addr, u16 reg, u8 val); -int sch56xx_read_virtual_reg16(u16 addr, u16 reg); -int sch56xx_read_virtual_reg12(u16 addr, u16 msb_reg, u16 lsn_reg, - int high_nibble); - -struct sch56xx_watchdog_data *sch56xx_watchdog_register( - u16 addr, u32 revision, struct mutex *io_lock, int check_enabled); -void sch56xx_watchdog_unregister(struct sch56xx_watchdog_data *data); diff --git a/ANDROID_3.4.5/drivers/hwmon/sht15.c b/ANDROID_3.4.5/drivers/hwmon/sht15.c deleted file mode 100644 index 8b011d01..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sht15.c +++ /dev/null @@ -1,1118 +0,0 @@ -/* - * sht15.c - support for the SHT15 Temperature and Humidity Sensor - * - * Portions Copyright (c) 2010-2011 Savoir-faire Linux Inc. - * Jerome Oufella - * Vivien Didelot - * - * Copyright (c) 2009 Jonathan Cameron - * - * Copyright (c) 2007 Wouter Horre - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * For further information, see the Documentation/hwmon/sht15 file. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Commands */ -#define SHT15_MEASURE_TEMP 0x03 -#define SHT15_MEASURE_RH 0x05 -#define SHT15_WRITE_STATUS 0x06 -#define SHT15_READ_STATUS 0x07 -#define SHT15_SOFT_RESET 0x1E - -/* Min timings */ -#define SHT15_TSCKL 100 /* (nsecs) clock low */ -#define SHT15_TSCKH 100 /* (nsecs) clock high */ -#define SHT15_TSU 150 /* (nsecs) data setup time */ -#define SHT15_TSRST 11 /* (msecs) soft reset time */ - -/* Status Register Bits */ -#define SHT15_STATUS_LOW_RESOLUTION 0x01 -#define SHT15_STATUS_NO_OTP_RELOAD 0x02 -#define SHT15_STATUS_HEATER 0x04 -#define SHT15_STATUS_LOW_BATTERY 0x40 - -/* Actions the driver may be doing */ -enum sht15_state { - SHT15_READING_NOTHING, - SHT15_READING_TEMP, - SHT15_READING_HUMID -}; - -/** - * struct sht15_temppair - elements of voltage dependent temp calc - * @vdd: supply voltage in microvolts - * @d1: see data sheet - */ -struct sht15_temppair { - int vdd; /* microvolts */ - int d1; -}; - -/* Table 9 from datasheet - relates temperature calculation to supply voltage */ -static const struct sht15_temppair temppoints[] = { - { 2500000, -39400 }, - { 3000000, -39600 }, - { 3500000, -39700 }, - { 4000000, -39800 }, - { 5000000, -40100 }, -}; - -/* Table from CRC datasheet, section 2.4 */ -static const u8 sht15_crc8_table[] = { - 0, 49, 98, 83, 196, 245, 166, 151, - 185, 136, 219, 234, 125, 76, 31, 46, - 67, 114, 33, 16, 135, 182, 229, 212, - 250, 203, 152, 169, 62, 15, 92, 109, - 134, 183, 228, 213, 66, 115, 32, 17, - 63, 14, 93, 108, 251, 202, 153, 168, - 197, 244, 167, 150, 1, 48, 99, 82, - 124, 77, 30, 47, 184, 137, 218, 235, - 61, 12, 95, 110, 249, 200, 155, 170, - 132, 181, 230, 215, 64, 113, 34, 19, - 126, 79, 28, 45, 186, 139, 216, 233, - 199, 246, 165, 148, 3, 50, 97, 80, - 187, 138, 217, 232, 127, 78, 29, 44, - 2, 51, 96, 81, 198, 247, 164, 149, - 248, 201, 154, 171, 60, 13, 94, 111, - 65, 112, 35, 18, 133, 180, 231, 214, - 122, 75, 24, 41, 190, 143, 220, 237, - 195, 242, 161, 144, 7, 54, 101, 84, - 57, 8, 91, 106, 253, 204, 159, 174, - 128, 177, 226, 211, 68, 117, 38, 23, - 252, 205, 158, 175, 56, 9, 90, 107, - 69, 116, 39, 22, 129, 176, 227, 210, - 191, 142, 221, 236, 123, 74, 25, 40, - 6, 55, 100, 85, 194, 243, 160, 145, - 71, 118, 37, 20, 131, 178, 225, 208, - 254, 207, 156, 173, 58, 11, 88, 105, - 4, 53, 102, 87, 192, 241, 162, 147, - 189, 140, 223, 238, 121, 72, 27, 42, - 193, 240, 163, 146, 5, 52, 103, 86, - 120, 73, 26, 43, 188, 141, 222, 239, - 130, 179, 224, 209, 70, 119, 36, 21, - 59, 10, 89, 104, 255, 206, 157, 172 -}; - -/** - * struct sht15_data - device instance specific data - * @pdata: platform data (gpio's etc). - * @read_work: bh of interrupt handler. - * @wait_queue: wait queue for getting values from device. - * @val_temp: last temperature value read from device. - * @val_humid: last humidity value read from device. - * @val_status: last status register value read from device. - * @checksum_ok: last value read from the device passed CRC validation. - * @checksumming: flag used to enable the data validation with CRC. - * @state: state identifying the action the driver is doing. - * @measurements_valid: are the current stored measures valid (start condition). - * @status_valid: is the current stored status valid (start condition). - * @last_measurement: time of last measure. - * @last_status: time of last status reading. - * @read_lock: mutex to ensure only one read in progress at a time. - * @dev: associate device structure. - * @hwmon_dev: device associated with hwmon subsystem. - * @reg: associated regulator (if specified). - * @nb: notifier block to handle notifications of voltage - * changes. - * @supply_uV: local copy of supply voltage used to allow use of - * regulator consumer if available. - * @supply_uV_valid: indicates that an updated value has not yet been - * obtained from the regulator and so any calculations - * based upon it will be invalid. - * @update_supply_work: work struct that is used to update the supply_uV. - * @interrupt_handled: flag used to indicate a handler has been scheduled. - */ -struct sht15_data { - struct sht15_platform_data *pdata; - struct work_struct read_work; - wait_queue_head_t wait_queue; - uint16_t val_temp; - uint16_t val_humid; - u8 val_status; - bool checksum_ok; - bool checksumming; - enum sht15_state state; - bool measurements_valid; - bool status_valid; - unsigned long last_measurement; - unsigned long last_status; - struct mutex read_lock; - struct device *dev; - struct device *hwmon_dev; - struct regulator *reg; - struct notifier_block nb; - int supply_uV; - bool supply_uV_valid; - struct work_struct update_supply_work; - atomic_t interrupt_handled; -}; - -/** - * sht15_reverse() - reverse a byte - * @byte: byte to reverse. - */ -static u8 sht15_reverse(u8 byte) -{ - u8 i, c; - - for (c = 0, i = 0; i < 8; i++) - c |= (!!(byte & (1 << i))) << (7 - i); - return c; -} - -/** - * sht15_crc8() - compute crc8 - * @data: sht15 specific data. - * @value: sht15 retrieved data. - * - * This implements section 2 of the CRC datasheet. - */ -static u8 sht15_crc8(struct sht15_data *data, - const u8 *value, - int len) -{ - u8 crc = sht15_reverse(data->val_status & 0x0F); - - while (len--) { - crc = sht15_crc8_table[*value ^ crc]; - value++; - } - - return crc; -} - -/** - * sht15_connection_reset() - reset the comms interface - * @data: sht15 specific data - * - * This implements section 3.4 of the data sheet - */ -static void sht15_connection_reset(struct sht15_data *data) -{ - int i; - - gpio_direction_output(data->pdata->gpio_data, 1); - ndelay(SHT15_TSCKL); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); - for (i = 0; i < 9; ++i) { - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); - } -} - -/** - * sht15_send_bit() - send an individual bit to the device - * @data: device state data - * @val: value of bit to be sent - */ -static inline void sht15_send_bit(struct sht15_data *data, int val) -{ - gpio_set_value(data->pdata->gpio_data, val); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); /* clock low time */ -} - -/** - * sht15_transmission_start() - specific sequence for new transmission - * @data: device state data - * - * Timings for this are not documented on the data sheet, so very - * conservative ones used in implementation. This implements - * figure 12 on the data sheet. - */ -static void sht15_transmission_start(struct sht15_data *data) -{ - /* ensure data is high and output */ - gpio_direction_output(data->pdata->gpio_data, 1); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - gpio_set_value(data->pdata->gpio_data, 0); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - gpio_set_value(data->pdata->gpio_data, 1); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); -} - -/** - * sht15_send_byte() - send a single byte to the device - * @data: device state - * @byte: value to be sent - */ -static void sht15_send_byte(struct sht15_data *data, u8 byte) -{ - int i; - - for (i = 0; i < 8; i++) { - sht15_send_bit(data, !!(byte & 0x80)); - byte <<= 1; - } -} - -/** - * sht15_wait_for_response() - checks for ack from device - * @data: device state - */ -static int sht15_wait_for_response(struct sht15_data *data) -{ - gpio_direction_input(data->pdata->gpio_data); - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - if (gpio_get_value(data->pdata->gpio_data)) { - gpio_set_value(data->pdata->gpio_sck, 0); - dev_err(data->dev, "Command not acknowledged\n"); - sht15_connection_reset(data); - return -EIO; - } - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); - return 0; -} - -/** - * sht15_send_cmd() - Sends a command to the device. - * @data: device state - * @cmd: command byte to be sent - * - * On entry, sck is output low, data is output pull high - * and the interrupt disabled. - */ -static int sht15_send_cmd(struct sht15_data *data, u8 cmd) -{ - int ret = 0; - - sht15_transmission_start(data); - sht15_send_byte(data, cmd); - ret = sht15_wait_for_response(data); - return ret; -} - -/** - * sht15_soft_reset() - send a soft reset command - * @data: sht15 specific data. - * - * As described in section 3.2 of the datasheet. - */ -static int sht15_soft_reset(struct sht15_data *data) -{ - int ret; - - ret = sht15_send_cmd(data, SHT15_SOFT_RESET); - if (ret) - return ret; - msleep(SHT15_TSRST); - /* device resets default hardware status register value */ - data->val_status = 0; - - return ret; -} - -/** - * sht15_ack() - send a ack - * @data: sht15 specific data. - * - * Each byte of data is acknowledged by pulling the data line - * low for one clock pulse. - */ -static void sht15_ack(struct sht15_data *data) -{ - gpio_direction_output(data->pdata->gpio_data, 0); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_data, 1); - - gpio_direction_input(data->pdata->gpio_data); -} - -/** - * sht15_end_transmission() - notify device of end of transmission - * @data: device state. - * - * This is basically a NAK (single clock pulse, data high). - */ -static void sht15_end_transmission(struct sht15_data *data) -{ - gpio_direction_output(data->pdata->gpio_data, 1); - ndelay(SHT15_TSU); - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); -} - -/** - * sht15_read_byte() - Read a byte back from the device - * @data: device state. - */ -static u8 sht15_read_byte(struct sht15_data *data) -{ - int i; - u8 byte = 0; - - for (i = 0; i < 8; ++i) { - byte <<= 1; - gpio_set_value(data->pdata->gpio_sck, 1); - ndelay(SHT15_TSCKH); - byte |= !!gpio_get_value(data->pdata->gpio_data); - gpio_set_value(data->pdata->gpio_sck, 0); - ndelay(SHT15_TSCKL); - } - return byte; -} - -/** - * sht15_send_status() - write the status register byte - * @data: sht15 specific data. - * @status: the byte to set the status register with. - * - * As described in figure 14 and table 5 of the datasheet. - */ -static int sht15_send_status(struct sht15_data *data, u8 status) -{ - int ret; - - ret = sht15_send_cmd(data, SHT15_WRITE_STATUS); - if (ret) - return ret; - gpio_direction_output(data->pdata->gpio_data, 1); - ndelay(SHT15_TSU); - sht15_send_byte(data, status); - ret = sht15_wait_for_response(data); - if (ret) - return ret; - - data->val_status = status; - return 0; -} - -/** - * sht15_update_status() - get updated status register from device if too old - * @data: device instance specific data. - * - * As described in figure 15 and table 5 of the datasheet. - */ -static int sht15_update_status(struct sht15_data *data) -{ - int ret = 0; - u8 status; - u8 previous_config; - u8 dev_checksum = 0; - u8 checksum_vals[2]; - int timeout = HZ; - - mutex_lock(&data->read_lock); - if (time_after(jiffies, data->last_status + timeout) - || !data->status_valid) { - ret = sht15_send_cmd(data, SHT15_READ_STATUS); - if (ret) - goto error_ret; - status = sht15_read_byte(data); - - if (data->checksumming) { - sht15_ack(data); - dev_checksum = sht15_reverse(sht15_read_byte(data)); - checksum_vals[0] = SHT15_READ_STATUS; - checksum_vals[1] = status; - data->checksum_ok = (sht15_crc8(data, checksum_vals, 2) - == dev_checksum); - } - - sht15_end_transmission(data); - - /* - * Perform checksum validation on the received data. - * Specification mentions that in case a checksum verification - * fails, a soft reset command must be sent to the device. - */ - if (data->checksumming && !data->checksum_ok) { - previous_config = data->val_status & 0x07; - ret = sht15_soft_reset(data); - if (ret) - goto error_ret; - if (previous_config) { - ret = sht15_send_status(data, previous_config); - if (ret) { - dev_err(data->dev, - "CRC validation failed, unable " - "to restore device settings\n"); - goto error_ret; - } - } - ret = -EAGAIN; - goto error_ret; - } - - data->val_status = status; - data->status_valid = true; - data->last_status = jiffies; - } -error_ret: - mutex_unlock(&data->read_lock); - - return ret; -} - -/** - * sht15_measurement() - get a new value from device - * @data: device instance specific data - * @command: command sent to request value - * @timeout_msecs: timeout after which comms are assumed - * to have failed are reset. - */ -static int sht15_measurement(struct sht15_data *data, - int command, - int timeout_msecs) -{ - int ret; - u8 previous_config; - - ret = sht15_send_cmd(data, command); - if (ret) - return ret; - - gpio_direction_input(data->pdata->gpio_data); - atomic_set(&data->interrupt_handled, 0); - - enable_irq(gpio_to_irq(data->pdata->gpio_data)); - if (gpio_get_value(data->pdata->gpio_data) == 0) { - disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); - /* Only relevant if the interrupt hasn't occurred. */ - if (!atomic_read(&data->interrupt_handled)) - schedule_work(&data->read_work); - } - ret = wait_event_timeout(data->wait_queue, - (data->state == SHT15_READING_NOTHING), - msecs_to_jiffies(timeout_msecs)); - if (ret == 0) {/* timeout occurred */ - disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); - sht15_connection_reset(data); - return -ETIME; - } - - /* - * Perform checksum validation on the received data. - * Specification mentions that in case a checksum verification fails, - * a soft reset command must be sent to the device. - */ - if (data->checksumming && !data->checksum_ok) { - previous_config = data->val_status & 0x07; - ret = sht15_soft_reset(data); - if (ret) - return ret; - if (previous_config) { - ret = sht15_send_status(data, previous_config); - if (ret) { - dev_err(data->dev, - "CRC validation failed, unable " - "to restore device settings\n"); - return ret; - } - } - return -EAGAIN; - } - - return 0; -} - -/** - * sht15_update_measurements() - get updated measures from device if too old - * @data: device state - */ -static int sht15_update_measurements(struct sht15_data *data) -{ - int ret = 0; - int timeout = HZ; - - mutex_lock(&data->read_lock); - if (time_after(jiffies, data->last_measurement + timeout) - || !data->measurements_valid) { - data->state = SHT15_READING_HUMID; - ret = sht15_measurement(data, SHT15_MEASURE_RH, 160); - if (ret) - goto error_ret; - data->state = SHT15_READING_TEMP; - ret = sht15_measurement(data, SHT15_MEASURE_TEMP, 400); - if (ret) - goto error_ret; - data->measurements_valid = true; - data->last_measurement = jiffies; - } -error_ret: - mutex_unlock(&data->read_lock); - - return ret; -} - -/** - * sht15_calc_temp() - convert the raw reading to a temperature - * @data: device state - * - * As per section 4.3 of the data sheet. - */ -static inline int sht15_calc_temp(struct sht15_data *data) -{ - int d1 = temppoints[0].d1; - int d2 = (data->val_status & SHT15_STATUS_LOW_RESOLUTION) ? 40 : 10; - int i; - - for (i = ARRAY_SIZE(temppoints) - 1; i > 0; i--) - /* Find pointer to interpolate */ - if (data->supply_uV > temppoints[i - 1].vdd) { - d1 = (data->supply_uV - temppoints[i - 1].vdd) - * (temppoints[i].d1 - temppoints[i - 1].d1) - / (temppoints[i].vdd - temppoints[i - 1].vdd) - + temppoints[i - 1].d1; - break; - } - - return data->val_temp * d2 + d1; -} - -/** - * sht15_calc_humid() - using last temperature convert raw to humid - * @data: device state - * - * This is the temperature compensated version as per section 4.2 of - * the data sheet. - * - * The sensor is assumed to be V3, which is compatible with V4. - * Humidity conversion coefficients are shown in table 7 of the datasheet. - */ -static inline int sht15_calc_humid(struct sht15_data *data) -{ - int rh_linear; /* milli percent */ - int temp = sht15_calc_temp(data); - int c2, c3; - int t2; - const int c1 = -4; - - if (data->val_status & SHT15_STATUS_LOW_RESOLUTION) { - c2 = 648000; /* x 10 ^ -6 */ - c3 = -7200; /* x 10 ^ -7 */ - t2 = 1280; - } else { - c2 = 40500; /* x 10 ^ -6 */ - c3 = -28; /* x 10 ^ -7 */ - t2 = 80; - } - - rh_linear = c1 * 1000 - + c2 * data->val_humid / 1000 - + (data->val_humid * data->val_humid * c3) / 10000; - return (temp - 25000) * (10000 + t2 * data->val_humid) - / 1000000 + rh_linear; -} - -/** - * sht15_show_status() - show status information in sysfs - * @dev: device. - * @attr: device attribute. - * @buf: sysfs buffer where information is written to. - * - * Will be called on read access to temp1_fault, humidity1_fault - * and heater_enable sysfs attributes. - * Returns number of bytes written into buffer, negative errno on error. - */ -static ssize_t sht15_show_status(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - struct sht15_data *data = dev_get_drvdata(dev); - u8 bit = to_sensor_dev_attr(attr)->index; - - ret = sht15_update_status(data); - - return ret ? ret : sprintf(buf, "%d\n", !!(data->val_status & bit)); -} - -/** - * sht15_store_heater() - change heater state via sysfs - * @dev: device. - * @attr: device attribute. - * @buf: sysfs buffer to read the new heater state from. - * @count: length of the data. - * - * Will be called on write access to heater_enable sysfs attribute. - * Returns number of bytes actually decoded, negative errno on error. - */ -static ssize_t sht15_store_heater(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - int ret; - struct sht15_data *data = dev_get_drvdata(dev); - long value; - u8 status; - - if (kstrtol(buf, 10, &value)) - return -EINVAL; - - mutex_lock(&data->read_lock); - status = data->val_status & 0x07; - if (!!value) - status |= SHT15_STATUS_HEATER; - else - status &= ~SHT15_STATUS_HEATER; - - ret = sht15_send_status(data, status); - mutex_unlock(&data->read_lock); - - return ret ? ret : count; -} - -/** - * sht15_show_temp() - show temperature measurement value in sysfs - * @dev: device. - * @attr: device attribute. - * @buf: sysfs buffer where measurement values are written to. - * - * Will be called on read access to temp1_input sysfs attribute. - * Returns number of bytes written into buffer, negative errno on error. - */ -static ssize_t sht15_show_temp(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - struct sht15_data *data = dev_get_drvdata(dev); - - /* Technically no need to read humidity as well */ - ret = sht15_update_measurements(data); - - return ret ? ret : sprintf(buf, "%d\n", - sht15_calc_temp(data)); -} - -/** - * sht15_show_humidity() - show humidity measurement value in sysfs - * @dev: device. - * @attr: device attribute. - * @buf: sysfs buffer where measurement values are written to. - * - * Will be called on read access to humidity1_input sysfs attribute. - * Returns number of bytes written into buffer, negative errno on error. - */ -static ssize_t sht15_show_humidity(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int ret; - struct sht15_data *data = dev_get_drvdata(dev); - - ret = sht15_update_measurements(data); - - return ret ? ret : sprintf(buf, "%d\n", sht15_calc_humid(data)); -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct platform_device *pdev = to_platform_device(dev); - return sprintf(buf, "%s\n", pdev->name); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, - sht15_show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, - sht15_show_humidity, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, sht15_show_status, NULL, - SHT15_STATUS_LOW_BATTERY); -static SENSOR_DEVICE_ATTR(humidity1_fault, S_IRUGO, sht15_show_status, NULL, - SHT15_STATUS_LOW_BATTERY); -static SENSOR_DEVICE_ATTR(heater_enable, S_IRUGO | S_IWUSR, sht15_show_status, - sht15_store_heater, SHT15_STATUS_HEATER); -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static struct attribute *sht15_attrs[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_humidity1_input.dev_attr.attr, - &sensor_dev_attr_temp1_fault.dev_attr.attr, - &sensor_dev_attr_humidity1_fault.dev_attr.attr, - &sensor_dev_attr_heater_enable.dev_attr.attr, - &dev_attr_name.attr, - NULL, -}; - -static const struct attribute_group sht15_attr_group = { - .attrs = sht15_attrs, -}; - -static irqreturn_t sht15_interrupt_fired(int irq, void *d) -{ - struct sht15_data *data = d; - - /* First disable the interrupt */ - disable_irq_nosync(irq); - atomic_inc(&data->interrupt_handled); - /* Then schedule a reading work struct */ - if (data->state != SHT15_READING_NOTHING) - schedule_work(&data->read_work); - return IRQ_HANDLED; -} - -static void sht15_bh_read_data(struct work_struct *work_s) -{ - uint16_t val = 0; - u8 dev_checksum = 0; - u8 checksum_vals[3]; - struct sht15_data *data - = container_of(work_s, struct sht15_data, - read_work); - - /* Firstly, verify the line is low */ - if (gpio_get_value(data->pdata->gpio_data)) { - /* - * If not, then start the interrupt again - care here as could - * have gone low in meantime so verify it hasn't! - */ - atomic_set(&data->interrupt_handled, 0); - enable_irq(gpio_to_irq(data->pdata->gpio_data)); - /* If still not occurred or another handler was scheduled */ - if (gpio_get_value(data->pdata->gpio_data) - || atomic_read(&data->interrupt_handled)) - return; - } - - /* Read the data back from the device */ - val = sht15_read_byte(data); - val <<= 8; - sht15_ack(data); - val |= sht15_read_byte(data); - - if (data->checksumming) { - /* - * Ask the device for a checksum and read it back. - * Note: the device sends the checksum byte reversed. - */ - sht15_ack(data); - dev_checksum = sht15_reverse(sht15_read_byte(data)); - checksum_vals[0] = (data->state == SHT15_READING_TEMP) ? - SHT15_MEASURE_TEMP : SHT15_MEASURE_RH; - checksum_vals[1] = (u8) (val >> 8); - checksum_vals[2] = (u8) val; - data->checksum_ok - = (sht15_crc8(data, checksum_vals, 3) == dev_checksum); - } - - /* Tell the device we are done */ - sht15_end_transmission(data); - - switch (data->state) { - case SHT15_READING_TEMP: - data->val_temp = val; - break; - case SHT15_READING_HUMID: - data->val_humid = val; - break; - default: - break; - } - - data->state = SHT15_READING_NOTHING; - wake_up(&data->wait_queue); -} - -static void sht15_update_voltage(struct work_struct *work_s) -{ - struct sht15_data *data - = container_of(work_s, struct sht15_data, - update_supply_work); - data->supply_uV = regulator_get_voltage(data->reg); -} - -/** - * sht15_invalidate_voltage() - mark supply voltage invalid when notified by reg - * @nb: associated notification structure - * @event: voltage regulator state change event code - * @ignored: function parameter - ignored here - * - * Note that as the notification code holds the regulator lock, we have - * to schedule an update of the supply voltage rather than getting it directly. - */ -static int sht15_invalidate_voltage(struct notifier_block *nb, - unsigned long event, - void *ignored) -{ - struct sht15_data *data = container_of(nb, struct sht15_data, nb); - - if (event == REGULATOR_EVENT_VOLTAGE_CHANGE) - data->supply_uV_valid = false; - schedule_work(&data->update_supply_work); - - return NOTIFY_OK; -} - -static int __devinit sht15_probe(struct platform_device *pdev) -{ - int ret; - struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL); - u8 status = 0; - - if (!data) { - ret = -ENOMEM; - dev_err(&pdev->dev, "kzalloc failed\n"); - goto error_ret; - } - - INIT_WORK(&data->read_work, sht15_bh_read_data); - INIT_WORK(&data->update_supply_work, sht15_update_voltage); - platform_set_drvdata(pdev, data); - mutex_init(&data->read_lock); - data->dev = &pdev->dev; - init_waitqueue_head(&data->wait_queue); - - if (pdev->dev.platform_data == NULL) { - ret = -EINVAL; - dev_err(&pdev->dev, "no platform data supplied\n"); - goto err_free_data; - } - data->pdata = pdev->dev.platform_data; - data->supply_uV = data->pdata->supply_mv * 1000; - if (data->pdata->checksum) - data->checksumming = true; - if (data->pdata->no_otp_reload) - status |= SHT15_STATUS_NO_OTP_RELOAD; - if (data->pdata->low_resolution) - status |= SHT15_STATUS_LOW_RESOLUTION; - - /* - * If a regulator is available, - * query what the supply voltage actually is! - */ - data->reg = regulator_get(data->dev, "vcc"); - if (!IS_ERR(data->reg)) { - int voltage; - - voltage = regulator_get_voltage(data->reg); - if (voltage) - data->supply_uV = voltage; - - regulator_enable(data->reg); - /* - * Setup a notifier block to update this if another device - * causes the voltage to change - */ - data->nb.notifier_call = &sht15_invalidate_voltage; - ret = regulator_register_notifier(data->reg, &data->nb); - if (ret) { - dev_err(&pdev->dev, - "regulator notifier request failed\n"); - regulator_disable(data->reg); - regulator_put(data->reg); - goto err_free_data; - } - } - - /* Try requesting the GPIOs */ - ret = gpio_request(data->pdata->gpio_sck, "SHT15 sck"); - if (ret) { - dev_err(&pdev->dev, "gpio request failed\n"); - goto err_release_reg; - } - gpio_direction_output(data->pdata->gpio_sck, 0); - - ret = gpio_request(data->pdata->gpio_data, "SHT15 data"); - if (ret) { - dev_err(&pdev->dev, "gpio request failed\n"); - goto err_release_gpio_sck; - } - - ret = request_irq(gpio_to_irq(data->pdata->gpio_data), - sht15_interrupt_fired, - IRQF_TRIGGER_FALLING, - "sht15 data", - data); - if (ret) { - dev_err(&pdev->dev, "failed to get irq for data line\n"); - goto err_release_gpio_data; - } - disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); - sht15_connection_reset(data); - ret = sht15_soft_reset(data); - if (ret) - goto err_release_irq; - - /* write status with platform data options */ - if (status) { - ret = sht15_send_status(data, status); - if (ret) - goto err_release_irq; - } - - ret = sysfs_create_group(&pdev->dev.kobj, &sht15_attr_group); - if (ret) { - dev_err(&pdev->dev, "sysfs create failed\n"); - goto err_release_irq; - } - - data->hwmon_dev = hwmon_device_register(data->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto err_release_sysfs_group; - } - - return 0; - -err_release_sysfs_group: - sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group); -err_release_irq: - free_irq(gpio_to_irq(data->pdata->gpio_data), data); -err_release_gpio_data: - gpio_free(data->pdata->gpio_data); -err_release_gpio_sck: - gpio_free(data->pdata->gpio_sck); -err_release_reg: - if (!IS_ERR(data->reg)) { - regulator_unregister_notifier(data->reg, &data->nb); - regulator_disable(data->reg); - regulator_put(data->reg); - } -err_free_data: - kfree(data); -error_ret: - return ret; -} - -static int __devexit sht15_remove(struct platform_device *pdev) -{ - struct sht15_data *data = platform_get_drvdata(pdev); - - /* - * Make sure any reads from the device are done and - * prevent new ones beginning - */ - mutex_lock(&data->read_lock); - if (sht15_soft_reset(data)) { - mutex_unlock(&data->read_lock); - return -EFAULT; - } - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group); - if (!IS_ERR(data->reg)) { - regulator_unregister_notifier(data->reg, &data->nb); - regulator_disable(data->reg); - regulator_put(data->reg); - } - - free_irq(gpio_to_irq(data->pdata->gpio_data), data); - gpio_free(data->pdata->gpio_data); - gpio_free(data->pdata->gpio_sck); - mutex_unlock(&data->read_lock); - kfree(data); - - return 0; -} - -/* - * sht_drivers simultaneously refers to __devinit and __devexit function - * which causes spurious section mismatch warning. So use __refdata to - * get rid from this. - */ -static struct platform_driver __refdata sht_drivers[] = { - { - .driver = { - .name = "sht10", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht11", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht15", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht71", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht75", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, -}; - -static int __init sht15_init(void) -{ - int ret; - int i; - - for (i = 0; i < ARRAY_SIZE(sht_drivers); i++) { - ret = platform_driver_register(&sht_drivers[i]); - if (ret) - goto error_unreg; - } - - return 0; - -error_unreg: - while (--i >= 0) - platform_driver_unregister(&sht_drivers[i]); - - return ret; -} -module_init(sht15_init); - -static void __exit sht15_exit(void) -{ - int i; - for (i = ARRAY_SIZE(sht_drivers) - 1; i >= 0; i--) - platform_driver_unregister(&sht_drivers[i]); -} -module_exit(sht15_exit); - -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/sht21.c b/ANDROID_3.4.5/drivers/hwmon/sht21.c deleted file mode 100644 index 6c2dede4..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sht21.c +++ /dev/null @@ -1,268 +0,0 @@ -/* Sensirion SHT21 humidity and temperature sensor driver - * - * Copyright (C) 2010 Urs Fleisch - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA - * - * Data sheet available (5/2010) at - * http://www.sensirion.com/en/pdf/product_information/Datasheet-humidity-sensor-SHT21.pdf - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* I2C command bytes */ -#define SHT21_TRIG_T_MEASUREMENT_HM 0xe3 -#define SHT21_TRIG_RH_MEASUREMENT_HM 0xe5 - -/** - * struct sht21 - SHT21 device specific data - * @hwmon_dev: device registered with hwmon - * @lock: mutex to protect measurement values - * @valid: only 0 before first measurement is taken - * @last_update: time of last update (jiffies) - * @temperature: cached temperature measurement value - * @humidity: cached humidity measurement value - */ -struct sht21 { - struct device *hwmon_dev; - struct mutex lock; - char valid; - unsigned long last_update; - int temperature; - int humidity; -}; - -/** - * sht21_temp_ticks_to_millicelsius() - convert raw temperature ticks to - * milli celsius - * @ticks: temperature ticks value received from sensor - */ -static inline int sht21_temp_ticks_to_millicelsius(int ticks) -{ - ticks &= ~0x0003; /* clear status bits */ - /* - * Formula T = -46.85 + 175.72 * ST / 2^16 from data sheet 6.2, - * optimized for integer fixed point (3 digits) arithmetic - */ - return ((21965 * ticks) >> 13) - 46850; -} - -/** - * sht21_rh_ticks_to_per_cent_mille() - convert raw humidity ticks to - * one-thousandths of a percent relative humidity - * @ticks: humidity ticks value received from sensor - */ -static inline int sht21_rh_ticks_to_per_cent_mille(int ticks) -{ - ticks &= ~0x0003; /* clear status bits */ - /* - * Formula RH = -6 + 125 * SRH / 2^16 from data sheet 6.1, - * optimized for integer fixed point (3 digits) arithmetic - */ - return ((15625 * ticks) >> 13) - 6000; -} - -/** - * sht21_update_measurements() - get updated measurements from device - * @client: I2C client device - * - * Returns 0 on success, else negative errno. - */ -static int sht21_update_measurements(struct i2c_client *client) -{ - int ret = 0; - struct sht21 *sht21 = i2c_get_clientdata(client); - - mutex_lock(&sht21->lock); - /* - * Data sheet 2.4: - * SHT2x should not be active for more than 10% of the time - e.g. - * maximum two measurements per second at 12bit accuracy shall be made. - */ - if (time_after(jiffies, sht21->last_update + HZ / 2) || !sht21->valid) { - ret = i2c_smbus_read_word_swapped(client, - SHT21_TRIG_T_MEASUREMENT_HM); - if (ret < 0) - goto out; - sht21->temperature = sht21_temp_ticks_to_millicelsius(ret); - ret = i2c_smbus_read_word_swapped(client, - SHT21_TRIG_RH_MEASUREMENT_HM); - if (ret < 0) - goto out; - sht21->humidity = sht21_rh_ticks_to_per_cent_mille(ret); - sht21->last_update = jiffies; - sht21->valid = 1; - } -out: - mutex_unlock(&sht21->lock); - - return ret >= 0 ? 0 : ret; -} - -/** - * sht21_show_temperature() - show temperature measurement value in sysfs - * @dev: device - * @attr: device attribute - * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to - * - * Will be called on read access to temp1_input sysfs attribute. - * Returns number of bytes written into buffer, negative errno on error. - */ -static ssize_t sht21_show_temperature(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sht21 *sht21 = i2c_get_clientdata(client); - int ret = sht21_update_measurements(client); - if (ret < 0) - return ret; - return sprintf(buf, "%d\n", sht21->temperature); -} - -/** - * sht21_show_humidity() - show humidity measurement value in sysfs - * @dev: device - * @attr: device attribute - * @buf: sysfs buffer (PAGE_SIZE) where measurement values are written to - * - * Will be called on read access to humidity1_input sysfs attribute. - * Returns number of bytes written into buffer, negative errno on error. - */ -static ssize_t sht21_show_humidity(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct i2c_client *client = to_i2c_client(dev); - struct sht21 *sht21 = i2c_get_clientdata(client); - int ret = sht21_update_measurements(client); - if (ret < 0) - return ret; - return sprintf(buf, "%d\n", sht21->humidity); -} - -/* sysfs attributes */ -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, - NULL, 0); -static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, - NULL, 0); - -static struct attribute *sht21_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_humidity1_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group sht21_attr_group = { - .attrs = sht21_attributes, -}; - -/** - * sht21_probe() - probe device - * @client: I2C client device - * @id: device ID - * - * Called by the I2C core when an entry in the ID table matches a - * device's name. - * Returns 0 on success. - */ -static int __devinit sht21_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct sht21 *sht21; - int err; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WORD_DATA)) { - dev_err(&client->dev, - "adapter does not support SMBus word transactions\n"); - return -ENODEV; - } - - sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL); - if (!sht21) { - dev_dbg(&client->dev, "kzalloc failed\n"); - return -ENOMEM; - } - i2c_set_clientdata(client, sht21); - - mutex_init(&sht21->lock); - - err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group); - if (err) { - dev_dbg(&client->dev, "could not create sysfs files\n"); - goto fail_free; - } - sht21->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(sht21->hwmon_dev)) { - dev_dbg(&client->dev, "unable to register hwmon device\n"); - err = PTR_ERR(sht21->hwmon_dev); - goto fail_remove_sysfs; - } - - dev_info(&client->dev, "initialized\n"); - - return 0; - -fail_remove_sysfs: - sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); -fail_free: - kfree(sht21); - - return err; -} - -/** - * sht21_remove() - remove device - * @client: I2C client device - */ -static int __devexit sht21_remove(struct i2c_client *client) -{ - struct sht21 *sht21 = i2c_get_clientdata(client); - - hwmon_device_unregister(sht21->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); - kfree(sht21); - - return 0; -} - -/* Device ID table */ -static const struct i2c_device_id sht21_id[] = { - { "sht21", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, sht21_id); - -static struct i2c_driver sht21_driver = { - .driver.name = "sht21", - .probe = sht21_probe, - .remove = __devexit_p(sht21_remove), - .id_table = sht21_id, -}; - -module_i2c_driver(sht21_driver); - -MODULE_AUTHOR("Urs Fleisch "); -MODULE_DESCRIPTION("Sensirion SHT21 humidity and temperature sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/sis5595.c b/ANDROID_3.4.5/drivers/hwmon/sis5595.c deleted file mode 100644 index 6c4d8eb9..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/sis5595.c +++ /dev/null @@ -1,942 +0,0 @@ -/* - * sis5595.c - Part of lm_sensors, Linux kernel modules - * for hardware monitoring - * - * Copyright (C) 1998 - 2001 Frodo Looijaard , - * Kyösti Mälkki , and - * Mark D. Studebaker - * Ported to Linux 2.6 by Aurelien Jarno with - * the help of Jean Delvare - * - * 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. - */ - -/* - * SiS southbridge has a LM78-like chip integrated on the same IC. - * This driver is a customized copy of lm78.c - * - * Supports following revisions: - * Version PCI ID PCI Revision - * 1 1039/0008 AF or less - * 2 1039/0008 B0 or greater - * - * Note: these chips contain a 0008 device which is incompatible with the - * 5595. We recognize these by the presence of the listed - * "blacklist" PCI ID and refuse to load. - * - * NOT SUPPORTED PCI ID BLACKLIST PCI ID - * 540 0008 0540 - * 550 0008 0550 - * 5513 0008 5511 - * 5581 0008 5597 - * 5582 0008 5597 - * 5597 0008 5597 - * 5598 0008 5597/5598 - * 630 0008 0630 - * 645 0008 0645 - * 730 0008 0730 - * 735 0008 0735 - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * If force_addr is set to anything different from 0, we forcibly enable - * the device at the given address. - */ -static u16 force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, - "Initialize the base address of the sensors"); - -static struct platform_device *pdev; - -/* Many SIS5595 constants specified below */ - -/* Length of ISA address segment */ -#define SIS5595_EXTENT 8 -/* PCI Config Registers */ -#define SIS5595_BASE_REG 0x68 -#define SIS5595_PIN_REG 0x7A -#define SIS5595_ENABLE_REG 0x7B - -/* Where are the ISA address/data registers relative to the base address */ -#define SIS5595_ADDR_REG_OFFSET 5 -#define SIS5595_DATA_REG_OFFSET 6 - -/* The SIS5595 registers */ -#define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2) -#define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2) -#define SIS5595_REG_IN(nr) (0x20 + (nr)) - -#define SIS5595_REG_FAN_MIN(nr) (0x3b + (nr)) -#define SIS5595_REG_FAN(nr) (0x28 + (nr)) - -/* - * On the first version of the chip, the temp registers are separate. - * On the second version, - * TEMP pin is shared with IN4, configured in PCI register 0x7A. - * The registers are the same as well. - * OVER and HYST are really MAX and MIN. - */ - -#define REV2MIN 0xb0 -#define SIS5595_REG_TEMP (((data->revision) >= REV2MIN) ? \ - SIS5595_REG_IN(4) : 0x27) -#define SIS5595_REG_TEMP_OVER (((data->revision) >= REV2MIN) ? \ - SIS5595_REG_IN_MAX(4) : 0x39) -#define SIS5595_REG_TEMP_HYST (((data->revision) >= REV2MIN) ? \ - SIS5595_REG_IN_MIN(4) : 0x3a) - -#define SIS5595_REG_CONFIG 0x40 -#define SIS5595_REG_ALARM1 0x41 -#define SIS5595_REG_ALARM2 0x42 -#define SIS5595_REG_FANDIV 0x47 - -/* - * Conversions. Limit checking is only done on the TO_REG - * variants. - */ - -/* - * IN: mV, (0V to 4.08V) - * REG: 16mV/bit - */ -static inline u8 IN_TO_REG(unsigned long val) -{ - unsigned long nval = SENSORS_LIMIT(val, 0, 4080); - return (nval + 8) / 16; -} -#define IN_FROM_REG(val) ((val) * 16) - -static inline u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm <= 0) - return 255; - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -static inline int FAN_FROM_REG(u8 val, int div) -{ - return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div); -} - -/* - * TEMP: mC (-54.12C to +157.53C) - * REG: 0.83C/bit + 52.12, two's complement - */ -static inline int TEMP_FROM_REG(s8 val) -{ - return val * 830 + 52120; -} -static inline s8 TEMP_TO_REG(int val) -{ - int nval = SENSORS_LIMIT(val, -54120, 157530) ; - return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830; -} - -/* - * FAN DIV: 1, 2, 4, or 8 (defaults to 2) - * REG: 0, 1, 2, or 3 (respectively) (defaults to 1) - */ -static inline u8 DIV_TO_REG(int val) -{ - return val == 8 ? 3 : val == 4 ? 2 : val == 1 ? 0 : 1; -} -#define DIV_FROM_REG(val) (1 << (val)) - -/* - * For each registered chip, we need to keep some data in memory. - * The structure is dynamically allocated. - */ -struct sis5595_data { - unsigned short addr; - const char *name; - struct device *hwmon_dev; - struct mutex lock; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - char maxins; /* == 3 if temp enabled, otherwise == 4 */ - u8 revision; /* Reg. value */ - - u8 in[5]; /* Register value */ - u8 in_max[5]; /* Register value */ - u8 in_min[5]; /* Register value */ - u8 fan[2]; /* Register value */ - u8 fan_min[2]; /* Register value */ - s8 temp; /* Register value */ - s8 temp_over; /* Register value */ - s8 temp_hyst; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ - u16 alarms; /* Register encoding, combined */ -}; - -static struct pci_dev *s_bridge; /* pointer to the (only) sis5595 */ - -static int sis5595_probe(struct platform_device *pdev); -static int __devexit sis5595_remove(struct platform_device *pdev); - -static int sis5595_read_value(struct sis5595_data *data, u8 reg); -static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value); -static struct sis5595_data *sis5595_update_device(struct device *dev); -static void sis5595_init_device(struct sis5595_data *data); - -static struct platform_driver sis5595_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "sis5595", - }, - .probe = sis5595_probe, - .remove = __devexit_p(sis5595_remove), -}; - -/* 4 Voltages */ -static ssize_t show_in(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr])); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr])); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr])); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val); - sis5595_write_value(data, SIS5595_REG_IN_MIN(nr), data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val); - sis5595_write_value(data, SIS5595_REG_IN_MAX(nr), data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_in_offset(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); - -show_in_offset(0); -show_in_offset(1); -show_in_offset(2); -show_in_offset(3); -show_in_offset(4); - -/* Temperature */ -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp)); -} - -static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over)); -} - -static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_over = TEMP_TO_REG(val); - sis5595_write_value(data, SIS5595_REG_TEMP_OVER, data->temp_over); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst)); -} - -static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_hyst = TEMP_TO_REG(val); - sis5595_write_value(data, SIS5595_REG_TEMP_HYST, data->temp_hyst); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL); -static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, - show_temp_over, set_temp_over); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, - show_temp_hyst, set_temp_hyst); - -/* 2 Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long min; - int reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - reg = sis5595_read_value(data, SIS5595_REG_FANDIV); - - switch (val) { - case 1: - data->fan_div[nr] = 0; - break; - case 2: - data->fan_div[nr] = 1; - break; - case 4: - data->fan_div[nr] = 2; - break; - case 8: - data->fan_div[nr] = 3; - break; - default: - dev_err(dev, "fan_div value %ld not " - "supported. Choose one of 1, 2, 4 or 8!\n", val); - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - switch (nr) { - case 0: - reg = (reg & 0xcf) | (data->fan_div[nr] << 4); - break; - case 1: - reg = (reg & 0x3f) | (data->fan_div[nr] << 6); - break; - } - sis5595_write_value(data, SIS5595_REG_FANDIV, reg); - data->fan_min[nr] = - FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1); - -show_fan_offset(1); -show_fan_offset(2); - -/* Alarms */ -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *da, - char *buf) -{ - struct sis5595_data *data = sis5595_update_device(dev); - int nr = to_sensor_dev_attr(da)->index; - return sprintf(buf, "%u\n", (data->alarms >> nr) & 1); -} -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, 15); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 15); - -static ssize_t show_name(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *sis5595_attributes[] = { - &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, - &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, - &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, - &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, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - - &dev_attr_alarms.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group sis5595_group = { - .attrs = sis5595_attributes, -}; - -static struct attribute *sis5595_attributes_in4[] = { - &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 -}; - -static const struct attribute_group sis5595_group_in4 = { - .attrs = sis5595_attributes_in4, -}; - -static struct attribute *sis5595_attributes_temp1[] = { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max.attr, - &dev_attr_temp1_max_hyst.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group sis5595_group_temp1 = { - .attrs = sis5595_attributes_temp1, -}; - -/* This is called when the module is loaded */ -static int __devinit sis5595_probe(struct platform_device *pdev) -{ - int err = 0; - int i; - struct sis5595_data *data; - struct resource *res; - char val; - - /* Reserve the ISA region */ - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, SIS5595_EXTENT, - sis5595_driver.driver.name)) { - err = -EBUSY; - goto exit; - } - - data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release; - } - - mutex_init(&data->lock); - mutex_init(&data->update_lock); - data->addr = res->start; - data->name = "sis5595"; - platform_set_drvdata(pdev, data); - - /* - * Check revision and pin registers to determine whether 4 or 5 voltages - */ - data->revision = s_bridge->revision; - /* 4 voltages, 1 temp */ - data->maxins = 3; - if (data->revision >= REV2MIN) { - pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val); - if (!(val & 0x80)) - /* 5 voltages, no temps */ - data->maxins = 4; - } - - /* Initialize the SIS5595 chip */ - sis5595_init_device(data); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 2; i++) { - data->fan_min[i] = sis5595_read_value(data, - SIS5595_REG_FAN_MIN(i)); - } - - /* Register sysfs hooks */ - err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group); - if (err) - goto exit_free; - if (data->maxins == 4) { - err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group_in4); - if (err) - goto exit_remove_files; - } else { - err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group_temp1); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1); -exit_free: - kfree(data); -exit_release: - release_region(res->start, SIS5595_EXTENT); -exit: - return err; -} - -static int __devexit sis5595_remove(struct platform_device *pdev) -{ - struct sis5595_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4); - sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1); - - release_region(data->addr, SIS5595_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - - -/* ISA access must be locked explicitly. */ -static int sis5595_read_value(struct sis5595_data *data, u8 reg) -{ - int res; - - mutex_lock(&data->lock); - outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET); - res = inb_p(data->addr + SIS5595_DATA_REG_OFFSET); - mutex_unlock(&data->lock); - return res; -} - -static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value) -{ - mutex_lock(&data->lock); - outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET); - outb_p(value, data->addr + SIS5595_DATA_REG_OFFSET); - mutex_unlock(&data->lock); -} - -/* Called when we have found a new SIS5595. */ -static void __devinit sis5595_init_device(struct sis5595_data *data) -{ - u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG); - if (!(config & 0x01)) - sis5595_write_value(data, SIS5595_REG_CONFIG, - (config & 0xf7) | 0x01); -} - -static struct sis5595_data *sis5595_update_device(struct device *dev) -{ - struct sis5595_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - - for (i = 0; i <= data->maxins; i++) { - data->in[i] = - sis5595_read_value(data, SIS5595_REG_IN(i)); - data->in_min[i] = - sis5595_read_value(data, - SIS5595_REG_IN_MIN(i)); - data->in_max[i] = - sis5595_read_value(data, - SIS5595_REG_IN_MAX(i)); - } - for (i = 0; i < 2; i++) { - data->fan[i] = - sis5595_read_value(data, SIS5595_REG_FAN(i)); - data->fan_min[i] = - sis5595_read_value(data, - SIS5595_REG_FAN_MIN(i)); - } - if (data->maxins == 3) { - data->temp = - sis5595_read_value(data, SIS5595_REG_TEMP); - data->temp_over = - sis5595_read_value(data, SIS5595_REG_TEMP_OVER); - data->temp_hyst = - sis5595_read_value(data, SIS5595_REG_TEMP_HYST); - } - i = sis5595_read_value(data, SIS5595_REG_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - data->alarms = - sis5595_read_value(data, SIS5595_REG_ALARM1) | - (sis5595_read_value(data, SIS5595_REG_ALARM2) << 8); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static DEFINE_PCI_DEVICE_TABLE(sis5595_pci_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, sis5595_pci_ids); - -static int blacklist[] __devinitdata = { - PCI_DEVICE_ID_SI_540, - PCI_DEVICE_ID_SI_550, - PCI_DEVICE_ID_SI_630, - PCI_DEVICE_ID_SI_645, - PCI_DEVICE_ID_SI_730, - PCI_DEVICE_ID_SI_735, - PCI_DEVICE_ID_SI_5511, /* - * 5513 chip has the 0008 device but - * that ID shows up in other chips so we - * use the 5511 ID for recognition - */ - PCI_DEVICE_ID_SI_5597, - PCI_DEVICE_ID_SI_5598, - 0 }; - -static int __devinit sis5595_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + SIS5595_EXTENT - 1, - .name = "sis5595", - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc("sis5595", address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - return err; -} - -static int __devinit sis5595_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - u16 address; - u8 enable; - int *i; - - for (i = blacklist; *i != 0; i++) { - struct pci_dev *d; - d = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL); - if (d) { - dev_err(&d->dev, - "Looked for SIS5595 but found unsupported device %.4x\n", - *i); - pci_dev_put(d); - return -ENODEV; - } - } - - force_addr &= ~(SIS5595_EXTENT - 1); - if (force_addr) { - dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", force_addr); - pci_write_config_word(dev, SIS5595_BASE_REG, force_addr); - } - - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, SIS5595_BASE_REG, &address)) { - dev_err(&dev->dev, "Failed to read ISA address\n"); - return -ENODEV; - } - - address &= ~(SIS5595_EXTENT - 1); - if (!address) { - dev_err(&dev->dev, - "Base address not set - upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - if (force_addr && address != force_addr) { - /* doesn't work for some chips? */ - dev_err(&dev->dev, "Failed to force ISA address\n"); - return -ENODEV; - } - - if (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) { - dev_err(&dev->dev, "Failed to read enable register\n"); - return -ENODEV; - } - if (!(enable & 0x80)) { - if ((PCIBIOS_SUCCESSFUL != - pci_write_config_byte(dev, SIS5595_ENABLE_REG, - enable | 0x80)) - || (PCIBIOS_SUCCESSFUL != - pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) - || (!(enable & 0x80))) { - /* doesn't work for some chips! */ - dev_err(&dev->dev, "Failed to enable HWM device\n"); - return -ENODEV; - } - } - - if (platform_driver_register(&sis5595_driver)) { - dev_dbg(&dev->dev, "Failed to register sis5595 driver\n"); - goto exit; - } - - s_bridge = pci_dev_get(dev); - /* Sets global pdev as a side effect */ - if (sis5595_device_add(address)) - goto exit_unregister; - - /* - * Always return failure here. This is to allow other drivers to bind - * to this pci device. We don't really want to have control over the - * pci device, we only wanted to read as few register values from it. - */ - return -ENODEV; - -exit_unregister: - pci_dev_put(dev); - platform_driver_unregister(&sis5595_driver); -exit: - return -ENODEV; -} - -static struct pci_driver sis5595_pci_driver = { - .name = "sis5595", - .id_table = sis5595_pci_ids, - .probe = sis5595_pci_probe, -}; - -static int __init sm_sis5595_init(void) -{ - return pci_register_driver(&sis5595_pci_driver); -} - -static void __exit sm_sis5595_exit(void) -{ - pci_unregister_driver(&sis5595_pci_driver); - if (s_bridge != NULL) { - platform_device_unregister(pdev); - platform_driver_unregister(&sis5595_driver); - pci_dev_put(s_bridge); - s_bridge = NULL; - } -} - -MODULE_AUTHOR("Aurelien Jarno "); -MODULE_DESCRIPTION("SiS 5595 Sensor device"); -MODULE_LICENSE("GPL"); - -module_init(sm_sis5595_init); -module_exit(sm_sis5595_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/smm665.c b/ANDROID_3.4.5/drivers/hwmon/smm665.c deleted file mode 100644 index cbc51fb3..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/smm665.c +++ /dev/null @@ -1,720 +0,0 @@ -/* - * Driver for SMM665 Power Controller / Monitor - * - * Copyright (C) 2010 Ericsson AB. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This driver should also work for SMM465, SMM764, and SMM766, but is untested - * for those chips. Only monitoring functionality is implemented. - * - * Datasheets: - * http://www.summitmicro.com/prod_select/summary/SMM665/SMM665B_2089_20.pdf - * http://www.summitmicro.com/prod_select/summary/SMM766B/SMM766B_2122.pdf - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Internal reference voltage (VREF, x 1000 */ -#define SMM665_VREF_ADC_X1000 1250 - -/* module parameters */ -static int vref = SMM665_VREF_ADC_X1000; -module_param(vref, int, 0); -MODULE_PARM_DESC(vref, "Reference voltage in mV"); - -enum chips { smm465, smm665, smm665c, smm764, smm766 }; - -/* - * ADC channel addresses - */ -#define SMM665_MISC16_ADC_DATA_A 0x00 -#define SMM665_MISC16_ADC_DATA_B 0x01 -#define SMM665_MISC16_ADC_DATA_C 0x02 -#define SMM665_MISC16_ADC_DATA_D 0x03 -#define SMM665_MISC16_ADC_DATA_E 0x04 -#define SMM665_MISC16_ADC_DATA_F 0x05 -#define SMM665_MISC16_ADC_DATA_VDD 0x06 -#define SMM665_MISC16_ADC_DATA_12V 0x07 -#define SMM665_MISC16_ADC_DATA_INT_TEMP 0x08 -#define SMM665_MISC16_ADC_DATA_AIN1 0x09 -#define SMM665_MISC16_ADC_DATA_AIN2 0x0a - -/* - * Command registers - */ -#define SMM665_MISC8_CMD_STS 0x80 -#define SMM665_MISC8_STATUS1 0x81 -#define SMM665_MISC8_STATUSS2 0x82 -#define SMM665_MISC8_IO_POLARITY 0x83 -#define SMM665_MISC8_PUP_POLARITY 0x84 -#define SMM665_MISC8_ADOC_STATUS1 0x85 -#define SMM665_MISC8_ADOC_STATUS2 0x86 -#define SMM665_MISC8_WRITE_PROT 0x87 -#define SMM665_MISC8_STS_TRACK 0x88 - -/* - * Configuration registers and register groups - */ -#define SMM665_ADOC_ENABLE 0x0d -#define SMM665_LIMIT_BASE 0x80 /* First limit register */ - -/* - * Limit register bit masks - */ -#define SMM665_TRIGGER_RST 0x8000 -#define SMM665_TRIGGER_HEALTHY 0x4000 -#define SMM665_TRIGGER_POWEROFF 0x2000 -#define SMM665_TRIGGER_SHUTDOWN 0x1000 -#define SMM665_ADC_MASK 0x03ff - -#define smm665_is_critical(lim) ((lim) & (SMM665_TRIGGER_RST \ - | SMM665_TRIGGER_POWEROFF \ - | SMM665_TRIGGER_SHUTDOWN)) -/* - * Fault register bit definitions - * Values are merged from status registers 1/2, - * with status register 1 providing the upper 8 bits. - */ -#define SMM665_FAULT_A 0x0001 -#define SMM665_FAULT_B 0x0002 -#define SMM665_FAULT_C 0x0004 -#define SMM665_FAULT_D 0x0008 -#define SMM665_FAULT_E 0x0010 -#define SMM665_FAULT_F 0x0020 -#define SMM665_FAULT_VDD 0x0040 -#define SMM665_FAULT_12V 0x0080 -#define SMM665_FAULT_TEMP 0x0100 -#define SMM665_FAULT_AIN1 0x0200 -#define SMM665_FAULT_AIN2 0x0400 - -/* - * I2C Register addresses - * - * The configuration register needs to be the configured base register. - * The command/status register address is derived from it. - */ -#define SMM665_REGMASK 0x78 -#define SMM665_CMDREG_BASE 0x48 -#define SMM665_CONFREG_BASE 0x50 - -/* - * Equations given by chip manufacturer to calculate voltage/temperature values - * vref = Reference voltage on VREF_ADC pin (module parameter) - * adc = 10bit ADC value read back from registers - */ - -/* Voltage A-F and VDD */ -#define SMM665_VMON_ADC_TO_VOLTS(adc) ((adc) * vref / 256) - -/* Voltage 12VIN */ -#define SMM665_12VIN_ADC_TO_VOLTS(adc) ((adc) * vref * 3 / 256) - -/* Voltage AIN1, AIN2 */ -#define SMM665_AIN_ADC_TO_VOLTS(adc) ((adc) * vref / 512) - -/* Temp Sensor */ -#define SMM665_TEMP_ADC_TO_CELSIUS(adc) (((adc) <= 511) ? \ - ((int)(adc) * 1000 / 4) : \ - (((int)(adc) - 0x400) * 1000 / 4)) - -#define SMM665_NUM_ADC 11 - -/* - * Chip dependent ADC conversion time, in uS - */ -#define SMM665_ADC_WAIT_SMM665 70 -#define SMM665_ADC_WAIT_SMM766 185 - -struct smm665_data { - enum chips type; - int conversion_time; /* ADC conversion time */ - struct device *hwmon_dev; - struct mutex update_lock; - bool valid; - unsigned long last_updated; /* in jiffies */ - u16 adc[SMM665_NUM_ADC]; /* adc values (raw) */ - u16 faults; /* fault status */ - /* The following values are in mV */ - int critical_min_limit[SMM665_NUM_ADC]; - int alarm_min_limit[SMM665_NUM_ADC]; - int critical_max_limit[SMM665_NUM_ADC]; - int alarm_max_limit[SMM665_NUM_ADC]; - struct i2c_client *cmdreg; -}; - -/* - * smm665_read16() - * - * Read 16 bit value from , . Upper 8 bits are in . - */ -static int smm665_read16(struct i2c_client *client, int reg) -{ - int rv, val; - - rv = i2c_smbus_read_byte_data(client, reg); - if (rv < 0) - return rv; - val = rv << 8; - rv = i2c_smbus_read_byte_data(client, reg + 1); - if (rv < 0) - return rv; - val |= rv; - return val; -} - -/* - * Read adc value. - */ -static int smm665_read_adc(struct smm665_data *data, int adc) -{ - struct i2c_client *client = data->cmdreg; - int rv; - int radc; - - /* - * Algorithm for reading ADC, per SMM665 datasheet - * - * {[S][addr][W][Ack]} {[offset][Ack]} {[S][addr][R][Nack]} - * [wait conversion time] - * {[S][addr][R][Ack]} {[datahi][Ack]} {[datalo][Ack][P]} - * - * To implement the first part of this exchange, - * do a full read transaction and expect a failure/Nack. - * This sets up the address pointer on the SMM665 - * and starts the ADC conversion. - * Then do a two-byte read transaction. - */ - rv = i2c_smbus_read_byte_data(client, adc << 3); - if (rv != -ENXIO) { - /* - * We expect ENXIO to reflect NACK - * (per Documentation/i2c/fault-codes). - * Everything else is an error. - */ - dev_dbg(&client->dev, - "Unexpected return code %d when setting ADC index", rv); - return (rv < 0) ? rv : -EIO; - } - - udelay(data->conversion_time); - - /* - * Now read two bytes. - * - * Neither i2c_smbus_read_byte() nor - * i2c_smbus_read_block_data() worked here, - * so use i2c_smbus_read_word_swapped() instead. - * We could also try to use i2c_master_recv(), - * but that is not always supported. - */ - rv = i2c_smbus_read_word_swapped(client, 0); - if (rv < 0) { - dev_dbg(&client->dev, "Failed to read ADC value: error %d", rv); - return -1; - } - /* - * Validate/verify readback adc channel (in bit 11..14). - */ - radc = (rv >> 11) & 0x0f; - if (radc != adc) { - dev_dbg(&client->dev, "Unexpected RADC: Expected %d got %d", - adc, radc); - return -EIO; - } - - return rv & SMM665_ADC_MASK; -} - -static struct smm665_data *smm665_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); - struct smm665_data *ret = data; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - int i, val; - - /* - * read status registers - */ - val = smm665_read16(client, SMM665_MISC8_STATUS1); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->faults = val; - - /* Read adc registers */ - for (i = 0; i < SMM665_NUM_ADC; i++) { - val = smm665_read_adc(data, i); - if (unlikely(val < 0)) { - ret = ERR_PTR(val); - goto abort; - } - data->adc[i] = val; - } - data->last_updated = jiffies; - data->valid = 1; - } -abort: - mutex_unlock(&data->update_lock); - return ret; -} - -/* Return converted value from given adc */ -static int smm665_convert(u16 adcval, int index) -{ - int val = 0; - - switch (index) { - case SMM665_MISC16_ADC_DATA_12V: - val = SMM665_12VIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); - break; - - case SMM665_MISC16_ADC_DATA_VDD: - case SMM665_MISC16_ADC_DATA_A: - case SMM665_MISC16_ADC_DATA_B: - case SMM665_MISC16_ADC_DATA_C: - case SMM665_MISC16_ADC_DATA_D: - case SMM665_MISC16_ADC_DATA_E: - case SMM665_MISC16_ADC_DATA_F: - val = SMM665_VMON_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); - break; - - case SMM665_MISC16_ADC_DATA_AIN1: - case SMM665_MISC16_ADC_DATA_AIN2: - val = SMM665_AIN_ADC_TO_VOLTS(adcval & SMM665_ADC_MASK); - break; - - case SMM665_MISC16_ADC_DATA_INT_TEMP: - val = SMM665_TEMP_ADC_TO_CELSIUS(adcval & SMM665_ADC_MASK); - break; - - default: - /* If we get here, the developer messed up */ - WARN_ON_ONCE(1); - break; - } - - return val; -} - -static int smm665_get_min(struct device *dev, int index) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); - - return data->alarm_min_limit[index]; -} - -static int smm665_get_max(struct device *dev, int index) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); - - return data->alarm_max_limit[index]; -} - -static int smm665_get_lcrit(struct device *dev, int index) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); - - return data->critical_min_limit[index]; -} - -static int smm665_get_crit(struct device *dev, int index) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); - - return data->critical_max_limit[index]; -} - -static ssize_t smm665_show_crit_alarm(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct smm665_data *data = smm665_update_device(dev); - int val = 0; - - if (IS_ERR(data)) - return PTR_ERR(data); - - if (data->faults & (1 << attr->index)) - val = 1; - - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -static ssize_t smm665_show_input(struct device *dev, - struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct smm665_data *data = smm665_update_device(dev); - int adc = attr->index; - int val; - - if (IS_ERR(data)) - return PTR_ERR(data); - - val = smm665_convert(data->adc[adc], adc); - return snprintf(buf, PAGE_SIZE, "%d\n", val); -} - -#define SMM665_SHOW(what) \ -static ssize_t smm665_show_##what(struct device *dev, \ - struct device_attribute *da, char *buf) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - const int val = smm665_get_##what(dev, attr->index); \ - return snprintf(buf, PAGE_SIZE, "%d\n", val); \ -} - -SMM665_SHOW(min); -SMM665_SHOW(max); -SMM665_SHOW(lcrit); -SMM665_SHOW(crit); - -/* - * These macros are used below in constructing device attribute objects - * for use with sysfs_create_group() to make a sysfs device file - * for each register. - */ - -#define SMM665_ATTR(name, type, cmd_idx) \ - static SENSOR_DEVICE_ATTR(name##_##type, S_IRUGO, \ - smm665_show_##type, NULL, cmd_idx) - -/* Construct a sensor_device_attribute structure for each register */ - -/* Input voltages */ -SMM665_ATTR(in1, input, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, input, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, input, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, input, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, input, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, input, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, input, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, input, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, input, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, input, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages min */ -SMM665_ATTR(in1, min, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, min, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, min, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, min, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, min, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, min, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, min, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, min, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, min, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, min, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages max */ -SMM665_ATTR(in1, max, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, max, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, max, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, max, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, max, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, max, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, max, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, max, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, max, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, max, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages lcrit */ -SMM665_ATTR(in1, lcrit, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, lcrit, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, lcrit, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, lcrit, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, lcrit, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, lcrit, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, lcrit, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, lcrit, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, lcrit, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, lcrit, SMM665_MISC16_ADC_DATA_AIN2); - -/* Input voltages crit */ -SMM665_ATTR(in1, crit, SMM665_MISC16_ADC_DATA_12V); -SMM665_ATTR(in2, crit, SMM665_MISC16_ADC_DATA_VDD); -SMM665_ATTR(in3, crit, SMM665_MISC16_ADC_DATA_A); -SMM665_ATTR(in4, crit, SMM665_MISC16_ADC_DATA_B); -SMM665_ATTR(in5, crit, SMM665_MISC16_ADC_DATA_C); -SMM665_ATTR(in6, crit, SMM665_MISC16_ADC_DATA_D); -SMM665_ATTR(in7, crit, SMM665_MISC16_ADC_DATA_E); -SMM665_ATTR(in8, crit, SMM665_MISC16_ADC_DATA_F); -SMM665_ATTR(in9, crit, SMM665_MISC16_ADC_DATA_AIN1); -SMM665_ATTR(in10, crit, SMM665_MISC16_ADC_DATA_AIN2); - -/* critical alarms */ -SMM665_ATTR(in1, crit_alarm, SMM665_FAULT_12V); -SMM665_ATTR(in2, crit_alarm, SMM665_FAULT_VDD); -SMM665_ATTR(in3, crit_alarm, SMM665_FAULT_A); -SMM665_ATTR(in4, crit_alarm, SMM665_FAULT_B); -SMM665_ATTR(in5, crit_alarm, SMM665_FAULT_C); -SMM665_ATTR(in6, crit_alarm, SMM665_FAULT_D); -SMM665_ATTR(in7, crit_alarm, SMM665_FAULT_E); -SMM665_ATTR(in8, crit_alarm, SMM665_FAULT_F); -SMM665_ATTR(in9, crit_alarm, SMM665_FAULT_AIN1); -SMM665_ATTR(in10, crit_alarm, SMM665_FAULT_AIN2); - -/* Temperature */ -SMM665_ATTR(temp1, input, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, min, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, max, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, lcrit, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, crit, SMM665_MISC16_ADC_DATA_INT_TEMP); -SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP); - -/* - * Finally, construct an array of pointers to members of the above objects, - * as required for sysfs_create_group() - */ -static struct attribute *smm665_attributes[] = { - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in1_crit.dev_attr.attr, - &sensor_dev_attr_in1_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in2_crit.dev_attr.attr, - &sensor_dev_attr_in2_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in3_crit.dev_attr.attr, - &sensor_dev_attr_in3_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in4_crit.dev_attr.attr, - &sensor_dev_attr_in4_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in5_crit.dev_attr.attr, - &sensor_dev_attr_in5_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in6_crit.dev_attr.attr, - &sensor_dev_attr_in6_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in7_crit.dev_attr.attr, - &sensor_dev_attr_in7_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in8_crit.dev_attr.attr, - &sensor_dev_attr_in8_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in9_crit.dev_attr.attr, - &sensor_dev_attr_in9_crit_alarm.dev_attr.attr, - - &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_lcrit.dev_attr.attr, - &sensor_dev_attr_in10_crit.dev_attr.attr, - &sensor_dev_attr_in10_crit_alarm.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_lcrit.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, - - NULL, -}; - -static const struct attribute_group smm665_group = { - .attrs = smm665_attributes, -}; - -static int smm665_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct i2c_adapter *adapter = client->adapter; - struct smm665_data *data; - int i, ret; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA - | I2C_FUNC_SMBUS_WORD_DATA)) - return -ENODEV; - - if (i2c_smbus_read_byte_data(client, SMM665_ADOC_ENABLE) < 0) - return -ENODEV; - - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - data->type = id->driver_data; - data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK) - | SMM665_CMDREG_BASE); - if (!data->cmdreg) - return -ENOMEM; - - switch (data->type) { - case smm465: - case smm665: - data->conversion_time = SMM665_ADC_WAIT_SMM665; - break; - case smm665c: - case smm764: - case smm766: - data->conversion_time = SMM665_ADC_WAIT_SMM766; - break; - } - - ret = -ENODEV; - if (i2c_smbus_read_byte_data(data->cmdreg, SMM665_MISC8_CMD_STS) < 0) - goto out_unregister; - - /* - * Read limits. - * - * Limit registers start with register SMM665_LIMIT_BASE. - * Each channel uses 8 registers, providing four limit values - * per channel. Each limit value requires two registers, with the - * high byte in the first register and the low byte in the second - * register. The first two limits are under limit values, followed - * by two over limit values. - * - * Limit register order matches the ADC register order, so we use - * ADC register defines throughout the code to index limit registers. - * - * We save the first retrieved value both as "critical" and "alarm" - * value. The second value overwrites either the critical or the - * alarm value, depending on its configuration. This ensures that both - * critical and alarm values are initialized, even if both registers are - * configured as critical or non-critical. - */ - for (i = 0; i < SMM665_NUM_ADC; i++) { - int val; - - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8); - if (unlikely(val < 0)) - goto out_unregister; - data->critical_min_limit[i] = data->alarm_min_limit[i] - = smm665_convert(val, i); - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 2); - if (unlikely(val < 0)) - goto out_unregister; - if (smm665_is_critical(val)) - data->critical_min_limit[i] = smm665_convert(val, i); - else - data->alarm_min_limit[i] = smm665_convert(val, i); - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 4); - if (unlikely(val < 0)) - goto out_unregister; - data->critical_max_limit[i] = data->alarm_max_limit[i] - = smm665_convert(val, i); - val = smm665_read16(client, SMM665_LIMIT_BASE + i * 8 + 6); - if (unlikely(val < 0)) - goto out_unregister; - if (smm665_is_critical(val)) - data->critical_max_limit[i] = smm665_convert(val, i); - else - data->alarm_max_limit[i] = smm665_convert(val, i); - } - - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, &smm665_group); - if (ret) - goto out_unregister; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_remove_group; - } - - return 0; - -out_remove_group: - sysfs_remove_group(&client->dev.kobj, &smm665_group); -out_unregister: - i2c_unregister_device(data->cmdreg); - return ret; -} - -static int smm665_remove(struct i2c_client *client) -{ - struct smm665_data *data = i2c_get_clientdata(client); - - i2c_unregister_device(data->cmdreg); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &smm665_group); - - return 0; -} - -static const struct i2c_device_id smm665_id[] = { - {"smm465", smm465}, - {"smm665", smm665}, - {"smm665c", smm665c}, - {"smm764", smm764}, - {"smm766", smm766}, - {} -}; - -MODULE_DEVICE_TABLE(i2c, smm665_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver smm665_driver = { - .driver = { - .name = "smm665", - }, - .probe = smm665_probe, - .remove = smm665_remove, - .id_table = smm665_id, -}; - -module_i2c_driver(smm665_driver); - -MODULE_AUTHOR("Guenter Roeck"); -MODULE_DESCRIPTION("SMM665 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/smsc47b397.c b/ANDROID_3.4.5/drivers/hwmon/smsc47b397.c deleted file mode 100644 index c5f6be47..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/smsc47b397.c +++ /dev/null @@ -1,422 +0,0 @@ -/* - * smsc47b397.c - Part of lm_sensors, Linux kernel modules - * for hardware monitoring - * - * Supports the SMSC LPC47B397-NC Super-I/O chip. - * - * Author/Maintainer: Mark M. Hoffman - * Copyright (C) 2004 Utilitek Systems, Inc. - * - * derived in part from smsc47m1.c: - * Copyright (C) 2002 Mark D. Studebaker - * Copyright (C) 2004 Jean Delvare - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static struct platform_device *pdev; - -#define DRVNAME "smsc47b397" - -/* Super-I/0 registers and commands */ - -#define REG 0x2e /* The register to read/write */ -#define VAL 0x2f /* The value to read/write */ - -static inline void superio_outb(int reg, int val) -{ - outb(reg, REG); - outb(val, VAL); -} - -static inline int superio_inb(int reg) -{ - outb(reg, REG); - return inb(VAL); -} - -/* select superio logical device */ -static inline void superio_select(int ld) -{ - superio_outb(0x07, ld); -} - -static inline void superio_enter(void) -{ - outb(0x55, REG); -} - -static inline void superio_exit(void) -{ - outb(0xAA, REG); -} - -#define SUPERIO_REG_DEVID 0x20 -#define SUPERIO_REG_DEVREV 0x21 -#define SUPERIO_REG_BASE_MSB 0x60 -#define SUPERIO_REG_BASE_LSB 0x61 -#define SUPERIO_REG_LD8 0x08 - -#define SMSC_EXTENT 0x02 - -/* 0 <= nr <= 3 */ -static u8 smsc47b397_reg_temp[] = {0x25, 0x26, 0x27, 0x80}; -#define SMSC47B397_REG_TEMP(nr) (smsc47b397_reg_temp[(nr)]) - -/* 0 <= nr <= 3 */ -#define SMSC47B397_REG_FAN_LSB(nr) (0x28 + 2 * (nr)) -#define SMSC47B397_REG_FAN_MSB(nr) (0x29 + 2 * (nr)) - -struct smsc47b397_data { - unsigned short addr; - const char *name; - struct device *hwmon_dev; - struct mutex lock; - - struct mutex update_lock; - unsigned long last_updated; /* in jiffies */ - int valid; - - /* register values */ - u16 fan[4]; - u8 temp[4]; -}; - -static int smsc47b397_read_value(struct smsc47b397_data *data, u8 reg) -{ - int res; - - mutex_lock(&data->lock); - outb(reg, data->addr); - res = inb_p(data->addr + 1); - mutex_unlock(&data->lock); - return res; -} - -static struct smsc47b397_data *smsc47b397_update_device(struct device *dev) -{ - struct smsc47b397_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - dev_dbg(dev, "starting device update...\n"); - - /* 4 temperature inputs, 4 fan inputs */ - for (i = 0; i < 4; i++) { - data->temp[i] = smsc47b397_read_value(data, - SMSC47B397_REG_TEMP(i)); - - /* must read LSB first */ - data->fan[i] = smsc47b397_read_value(data, - SMSC47B397_REG_FAN_LSB(i)); - data->fan[i] |= smsc47b397_read_value(data, - SMSC47B397_REG_FAN_MSB(i)) << 8; - } - - data->last_updated = jiffies; - data->valid = 1; - - dev_dbg(dev, "... device update complete\n"); - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* - * TEMP: 0.001C/bit (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static int temp_from_reg(u8 reg) -{ - return (s8)reg * 1000; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47b397_data *data = smsc47b397_update_device(dev); - return sprintf(buf, "%d\n", temp_from_reg(data->temp[attr->index])); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3); - -/* - * FAN: 1 RPM/bit - * REG: count of 90kHz pulses / revolution - */ -static int fan_from_reg(u16 reg) -{ - if (reg == 0 || reg == 0xffff) - return 0; - return 90000 * 60 / reg; -} - -static ssize_t show_fan(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47b397_data *data = smsc47b397_update_device(dev); - return sprintf(buf, "%d\n", fan_from_reg(data->fan[attr->index])); -} -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3); - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct smsc47b397_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *smsc47b397_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan4_input.dev_attr.attr, - - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group smsc47b397_group = { - .attrs = smsc47b397_attributes, -}; - -static int __devexit smsc47b397_remove(struct platform_device *pdev) -{ - struct smsc47b397_data *data = platform_get_drvdata(pdev); - struct resource *res; - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &smsc47b397_group); - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, SMSC_EXTENT); - kfree(data); - - return 0; -} - -static int smsc47b397_probe(struct platform_device *pdev); - -static struct platform_driver smsc47b397_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = smsc47b397_probe, - .remove = __devexit_p(smsc47b397_remove), -}; - -static int __devinit smsc47b397_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct smsc47b397_data *data; - struct resource *res; - int err = 0; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, SMSC_EXTENT, - smsc47b397_driver.driver.name)) { - dev_err(dev, "Region 0x%lx-0x%lx already in use!\n", - (unsigned long)res->start, - (unsigned long)res->start + SMSC_EXTENT - 1); - return -EBUSY; - } - - data = kzalloc(sizeof(struct smsc47b397_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto error_release; - } - - data->addr = res->start; - data->name = "smsc47b397"; - mutex_init(&data->lock); - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - err = sysfs_create_group(&dev->kobj, &smsc47b397_group); - if (err) - goto error_free; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_remove; - } - - return 0; - -error_remove: - sysfs_remove_group(&dev->kobj, &smsc47b397_group); -error_free: - kfree(data); -error_release: - release_region(res->start, SMSC_EXTENT); - return err; -} - -static int __init smsc47b397_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + SMSC_EXTENT - 1, - .name = DRVNAME, - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init smsc47b397_find(void) -{ - u8 id, rev; - char *name; - unsigned short addr; - - superio_enter(); - id = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); - - switch (id) { - case 0x81: - name = "SCH5307-NS"; - break; - case 0x6f: - name = "LPC47B397-NC"; - break; - case 0x85: - case 0x8c: - name = "SCH5317"; - break; - default: - superio_exit(); - return -ENODEV; - } - - rev = superio_inb(SUPERIO_REG_DEVREV); - - superio_select(SUPERIO_REG_LD8); - addr = (superio_inb(SUPERIO_REG_BASE_MSB) << 8) - | superio_inb(SUPERIO_REG_BASE_LSB); - - pr_info("found SMSC %s (base address 0x%04x, revision %u)\n", - name, addr, rev); - - superio_exit(); - return addr; -} - -static int __init smsc47b397_init(void) -{ - unsigned short address; - int ret; - - ret = smsc47b397_find(); - if (ret < 0) - return ret; - address = ret; - - ret = platform_driver_register(&smsc47b397_driver); - if (ret) - goto exit; - - /* Sets global pdev as a side effect */ - ret = smsc47b397_device_add(address); - if (ret) - goto exit_driver; - - return 0; - -exit_driver: - platform_driver_unregister(&smsc47b397_driver); -exit: - return ret; -} - -static void __exit smsc47b397_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&smsc47b397_driver); -} - -MODULE_AUTHOR("Mark M. Hoffman "); -MODULE_DESCRIPTION("SMSC LPC47B397 driver"); -MODULE_LICENSE("GPL"); - -module_init(smsc47b397_init); -module_exit(smsc47b397_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/smsc47m1.c b/ANDROID_3.4.5/drivers/hwmon/smsc47m1.c deleted file mode 100644 index b5aa38dd..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/smsc47m1.c +++ /dev/null @@ -1,975 +0,0 @@ -/* - * smsc47m1.c - Part of lm_sensors, Linux kernel modules - * for hardware monitoring - * - * Supports the SMSC LPC47B27x, LPC47M10x, LPC47M112, LPC47M13x, - * LPC47M14x, LPC47M15x, LPC47M192, LPC47M292 and LPC47M997 - * Super-I/O chips. - * - * Copyright (C) 2002 Mark D. Studebaker - * Copyright (C) 2004-2007 Jean Delvare - * Ported to Linux 2.6 by Gabriele Gorla - * and Jean Delvare - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static struct platform_device *pdev; - -#define DRVNAME "smsc47m1" -enum chips { smsc47m1, smsc47m2 }; - -/* Super-I/0 registers and commands */ - -#define REG 0x2e /* The register to read/write */ -#define VAL 0x2f /* The value to read/write */ - -static inline void -superio_outb(int reg, int val) -{ - outb(reg, REG); - outb(val, VAL); -} - -static inline int -superio_inb(int reg) -{ - outb(reg, REG); - return inb(VAL); -} - -/* logical device for fans is 0x0A */ -#define superio_select() superio_outb(0x07, 0x0A) - -static inline void -superio_enter(void) -{ - outb(0x55, REG); -} - -static inline void -superio_exit(void) -{ - outb(0xAA, REG); -} - -#define SUPERIO_REG_ACT 0x30 -#define SUPERIO_REG_BASE 0x60 -#define SUPERIO_REG_DEVID 0x20 -#define SUPERIO_REG_DEVREV 0x21 - -/* Logical device registers */ - -#define SMSC_EXTENT 0x80 - -/* nr is 0 or 1 in the macros below */ -#define SMSC47M1_REG_ALARM 0x04 -#define SMSC47M1_REG_TPIN(nr) (0x34 - (nr)) -#define SMSC47M1_REG_PPIN(nr) (0x36 - (nr)) -#define SMSC47M1_REG_FANDIV 0x58 - -static const u8 SMSC47M1_REG_FAN[3] = { 0x59, 0x5a, 0x6b }; -static const u8 SMSC47M1_REG_FAN_PRELOAD[3] = { 0x5b, 0x5c, 0x6c }; -static const u8 SMSC47M1_REG_PWM[3] = { 0x56, 0x57, 0x69 }; - -#define SMSC47M2_REG_ALARM6 0x09 -#define SMSC47M2_REG_TPIN1 0x38 -#define SMSC47M2_REG_TPIN2 0x37 -#define SMSC47M2_REG_TPIN3 0x2d -#define SMSC47M2_REG_PPIN3 0x2c -#define SMSC47M2_REG_FANDIV3 0x6a - -#define MIN_FROM_REG(reg, div) ((reg) >= 192 ? 0 : \ - 983040 / ((192 - (reg)) * (div))) -#define FAN_FROM_REG(reg, div, preload) ((reg) <= (preload) || (reg) == 255 ? \ - 0 : \ - 983040 / (((reg) - (preload)) * (div))) -#define DIV_FROM_REG(reg) (1 << (reg)) -#define PWM_FROM_REG(reg) (((reg) & 0x7E) << 1) -#define PWM_EN_FROM_REG(reg) ((~(reg)) & 0x01) -#define PWM_TO_REG(reg) (((reg) >> 1) & 0x7E) - -struct smsc47m1_data { - unsigned short addr; - const char *name; - enum chips type; - struct device *hwmon_dev; - - struct mutex update_lock; - unsigned long last_updated; /* In jiffies */ - - u8 fan[3]; /* Register value */ - u8 fan_preload[3]; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 alarms; /* Register encoding */ - u8 pwm[3]; /* Register value (bit 0 is disable) */ -}; - -struct smsc47m1_sio_data { - enum chips type; - u8 activate; /* Remember initial device state */ -}; - - -static int __exit smsc47m1_remove(struct platform_device *pdev); -static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, - int init); - -static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg) -{ - return inb_p(data->addr + reg); -} - -static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg, - u8 value) -{ - outb_p(value, data->addr + reg); -} - -static struct platform_driver smsc47m1_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .remove = __exit_p(smsc47m1_remove), -}; - -static ssize_t get_fan(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - int nr = attr->index; - /* - * This chip (stupidly) stops monitoring fan speed if PWM is - * enabled and duty cycle is 0%. This is fine if the monitoring - * and control concern the same fan, but troublesome if they are - * not (which could as well happen). - */ - int rpm = (data->pwm[nr] & 0x7F) == 0x00 ? 0 : - FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]), - data->fan_preload[nr]); - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t get_fan_min(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - int nr = attr->index; - int rpm = MIN_FROM_REG(data->fan_preload[nr], - DIV_FROM_REG(data->fan_div[nr])); - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t get_fan_div(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index])); -} - -static ssize_t get_fan_alarm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - int bitnr = to_sensor_dev_attr(devattr)->index; - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -static ssize_t get_pwm(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - return sprintf(buf, "%d\n", PWM_FROM_REG(data->pwm[attr->index])); -} - -static ssize_t get_pwm_en(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - return sprintf(buf, "%d\n", PWM_EN_FROM_REG(data->pwm[attr->index])); -} - -static ssize_t get_alarms(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct smsc47m1_data *data = smsc47m1_update_device(dev, 0); - return sprintf(buf, "%d\n", data->alarms); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = dev_get_drvdata(dev); - int nr = attr->index; - long rpmdiv; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - rpmdiv = val * DIV_FROM_REG(data->fan_div[nr]); - - if (983040 > 192 * rpmdiv || 2 * rpmdiv > 983040) { - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - data->fan_preload[nr] = 192 - ((983040 + rpmdiv / 2) / rpmdiv); - smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr], - data->fan_preload[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan clock divider. This follows the principle - * of least surprise; the user doesn't expect the fan minimum to change just - * because the divider changed. - */ -static ssize_t set_fan_div(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = dev_get_drvdata(dev); - int nr = attr->index; - long new_div; - int err; - long tmp; - u8 old_div = DIV_FROM_REG(data->fan_div[nr]); - - err = kstrtol(buf, 10, &new_div); - if (err) - return err; - - if (new_div == old_div) /* No change */ - return count; - - mutex_lock(&data->update_lock); - switch (new_div) { - case 1: - data->fan_div[nr] = 0; - break; - case 2: - data->fan_div[nr] = 1; - break; - case 4: - data->fan_div[nr] = 2; - break; - case 8: - data->fan_div[nr] = 3; - break; - default: - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - switch (nr) { - case 0: - case 1: - tmp = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV) - & ~(0x03 << (4 + 2 * nr)); - tmp |= data->fan_div[nr] << (4 + 2 * nr); - smsc47m1_write_value(data, SMSC47M1_REG_FANDIV, tmp); - break; - case 2: - tmp = smsc47m1_read_value(data, SMSC47M2_REG_FANDIV3) & 0xCF; - tmp |= data->fan_div[2] << 4; - smsc47m1_write_value(data, SMSC47M2_REG_FANDIV3, tmp); - break; - } - - /* Preserve fan min */ - tmp = 192 - (old_div * (192 - data->fan_preload[nr]) - + new_div / 2) / new_div; - data->fan_preload[nr] = SENSORS_LIMIT(tmp, 0, 191); - smsc47m1_write_value(data, SMSC47M1_REG_FAN_PRELOAD[nr], - data->fan_preload[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = dev_get_drvdata(dev); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - if (val < 0 || val > 255) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm[nr] &= 0x81; /* Preserve additional bits */ - data->pwm[nr] |= PWM_TO_REG(val); - smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr], - data->pwm[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t set_pwm_en(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct smsc47m1_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm[nr] &= 0xFE; /* preserve the other bits */ - data->pwm[nr] |= !val; - smsc47m1_write_value(data, SMSC47M1_REG_PWM[nr], - data->pwm[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -#define fan_present(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, get_fan, \ - NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - get_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - get_fan_div, set_fan_div, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_alarm, S_IRUGO, get_fan_alarm, \ - NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR, \ - get_pwm, set_pwm, offset - 1); \ -static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR, \ - get_pwm_en, set_pwm_en, offset - 1) - -fan_present(1); -fan_present(2); -fan_present(3); - -static DEVICE_ATTR(alarms, S_IRUGO, get_alarms, NULL); - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct smsc47m1_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *smsc47m1_attributes_fan1[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group_fan1 = { - .attrs = smsc47m1_attributes_fan1, -}; - -static struct attribute *smsc47m1_attributes_fan2[] = { - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group_fan2 = { - .attrs = smsc47m1_attributes_fan2, -}; - -static struct attribute *smsc47m1_attributes_fan3[] = { - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group_fan3 = { - .attrs = smsc47m1_attributes_fan3, -}; - -static struct attribute *smsc47m1_attributes_pwm1[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group_pwm1 = { - .attrs = smsc47m1_attributes_pwm1, -}; - -static struct attribute *smsc47m1_attributes_pwm2[] = { - &sensor_dev_attr_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group_pwm2 = { - .attrs = smsc47m1_attributes_pwm2, -}; - -static struct attribute *smsc47m1_attributes_pwm3[] = { - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group_pwm3 = { - .attrs = smsc47m1_attributes_pwm3, -}; - -static struct attribute *smsc47m1_attributes[] = { - &dev_attr_alarms.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group smsc47m1_group = { - .attrs = smsc47m1_attributes, -}; - -static int __init smsc47m1_find(struct smsc47m1_sio_data *sio_data) -{ - u8 val; - unsigned short addr; - - superio_enter(); - val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID); - - /* - * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x - * (device id 0x5F) and LPC47B27x (device id 0x51) have fan control. - * The LPC47M15x and LPC47M192 chips "with hardware monitoring block" - * can do much more besides (device id 0x60). - * The LPC47M997 is undocumented, but seems to be compatible with - * the LPC47M192, and has the same device id. - * The LPC47M292 (device id 0x6B) is somewhat compatible, but it - * supports a 3rd fan, and the pin configuration registers are - * unfortunately different. - * The LPC47M233 has the same device id (0x6B) but is not compatible. - * We check the high bit of the device revision register to - * differentiate them. - */ - switch (val) { - case 0x51: - pr_info("Found SMSC LPC47B27x\n"); - sio_data->type = smsc47m1; - break; - case 0x59: - pr_info("Found SMSC LPC47M10x/LPC47M112/LPC47M13x\n"); - sio_data->type = smsc47m1; - break; - case 0x5F: - pr_info("Found SMSC LPC47M14x\n"); - sio_data->type = smsc47m1; - break; - case 0x60: - pr_info("Found SMSC LPC47M15x/LPC47M192/LPC47M997\n"); - sio_data->type = smsc47m1; - break; - case 0x6B: - if (superio_inb(SUPERIO_REG_DEVREV) & 0x80) { - pr_debug("Found SMSC LPC47M233, unsupported\n"); - superio_exit(); - return -ENODEV; - } - - pr_info("Found SMSC LPC47M292\n"); - sio_data->type = smsc47m2; - break; - default: - superio_exit(); - return -ENODEV; - } - - superio_select(); - addr = (superio_inb(SUPERIO_REG_BASE) << 8) - | superio_inb(SUPERIO_REG_BASE + 1); - if (addr == 0) { - pr_info("Device address not set, will not use\n"); - superio_exit(); - return -ENODEV; - } - - /* - * Enable only if address is set (needed at least on the - * Compaq Presario S4000NX) - */ - sio_data->activate = superio_inb(SUPERIO_REG_ACT); - if ((sio_data->activate & 0x01) == 0) { - pr_info("Enabling device\n"); - superio_outb(SUPERIO_REG_ACT, sio_data->activate | 0x01); - } - - superio_exit(); - return addr; -} - -/* Restore device to its initial state */ -static void smsc47m1_restore(const struct smsc47m1_sio_data *sio_data) -{ - if ((sio_data->activate & 0x01) == 0) { - superio_enter(); - superio_select(); - - pr_info("Disabling device\n"); - superio_outb(SUPERIO_REG_ACT, sio_data->activate); - - superio_exit(); - } -} - -#define CHECK 1 -#define REQUEST 2 -#define RELEASE 3 - -/* - * This function can be used to: - * - test for resource conflicts with ACPI - * - request the resources - * - release the resources - * We only allocate the I/O ports we really need, to minimize the risk of - * conflicts with ACPI or with other drivers. - */ -static int smsc47m1_handle_resources(unsigned short address, enum chips type, - int action, struct device *dev) -{ - static const u8 ports_m1[] = { - /* register, region length */ - 0x04, 1, - 0x33, 4, - 0x56, 7, - }; - - static const u8 ports_m2[] = { - /* register, region length */ - 0x04, 1, - 0x09, 1, - 0x2c, 2, - 0x35, 4, - 0x56, 7, - 0x69, 4, - }; - - int i, ports_size, err; - const u8 *ports; - - switch (type) { - case smsc47m1: - default: - ports = ports_m1; - ports_size = ARRAY_SIZE(ports_m1); - break; - case smsc47m2: - ports = ports_m2; - ports_size = ARRAY_SIZE(ports_m2); - break; - } - - for (i = 0; i + 1 < ports_size; i += 2) { - unsigned short start = address + ports[i]; - unsigned short len = ports[i + 1]; - - switch (action) { - case CHECK: - /* Only check for conflicts */ - err = acpi_check_region(start, len, DRVNAME); - if (err) - return err; - break; - case REQUEST: - /* Request the resources */ - if (!request_region(start, len, DRVNAME)) { - dev_err(dev, "Region 0x%hx-0x%hx already in " - "use!\n", start, start + len); - - /* Undo all requests */ - for (i -= 2; i >= 0; i -= 2) - release_region(address + ports[i], - ports[i + 1]); - return -EBUSY; - } - break; - case RELEASE: - /* Release the resources */ - release_region(start, len); - break; - } - } - - return 0; -} - -static void smsc47m1_remove_files(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &smsc47m1_group); - sysfs_remove_group(&dev->kobj, &smsc47m1_group_fan1); - sysfs_remove_group(&dev->kobj, &smsc47m1_group_fan2); - sysfs_remove_group(&dev->kobj, &smsc47m1_group_fan3); - sysfs_remove_group(&dev->kobj, &smsc47m1_group_pwm1); - sysfs_remove_group(&dev->kobj, &smsc47m1_group_pwm2); - sysfs_remove_group(&dev->kobj, &smsc47m1_group_pwm3); -} - -static int __init smsc47m1_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct smsc47m1_sio_data *sio_data = dev->platform_data; - struct smsc47m1_data *data; - struct resource *res; - int err; - int fan1, fan2, fan3, pwm1, pwm2, pwm3; - - static const char * const names[] = { - "smsc47m1", - "smsc47m2", - }; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - err = smsc47m1_handle_resources(res->start, sio_data->type, - REQUEST, dev); - if (err < 0) - return err; - - data = kzalloc(sizeof(struct smsc47m1_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto error_release; - } - - data->addr = res->start; - data->type = sio_data->type; - data->name = names[sio_data->type]; - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - /* - * If no function is properly configured, there's no point in - * actually registering the chip. - */ - pwm1 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(0)) & 0x05) - == 0x04; - pwm2 = (smsc47m1_read_value(data, SMSC47M1_REG_PPIN(1)) & 0x05) - == 0x04; - if (data->type == smsc47m2) { - fan1 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN1) - & 0x0d) == 0x09; - fan2 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN2) - & 0x0d) == 0x09; - fan3 = (smsc47m1_read_value(data, SMSC47M2_REG_TPIN3) - & 0x0d) == 0x0d; - pwm3 = (smsc47m1_read_value(data, SMSC47M2_REG_PPIN3) - & 0x0d) == 0x08; - } else { - fan1 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(0)) - & 0x05) == 0x05; - fan2 = (smsc47m1_read_value(data, SMSC47M1_REG_TPIN(1)) - & 0x05) == 0x05; - fan3 = 0; - pwm3 = 0; - } - if (!(fan1 || fan2 || fan3 || pwm1 || pwm2 || pwm3)) { - dev_warn(dev, "Device not configured, will not use\n"); - err = -ENODEV; - goto error_free; - } - - /* - * Some values (fan min, clock dividers, pwm registers) may be - * needed before any update is triggered, so we better read them - * at least once here. We don't usually do it that way, but in - * this particular case, manually reading 5 registers out of 8 - * doesn't make much sense and we're better using the existing - * function. - */ - smsc47m1_update_device(dev, 1); - - /* Register sysfs hooks */ - if (fan1) { - err = sysfs_create_group(&dev->kobj, - &smsc47m1_group_fan1); - if (err) - goto error_remove_files; - } else - dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n"); - - if (fan2) { - err = sysfs_create_group(&dev->kobj, - &smsc47m1_group_fan2); - if (err) - goto error_remove_files; - } else - dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n"); - - if (fan3) { - err = sysfs_create_group(&dev->kobj, - &smsc47m1_group_fan3); - if (err) - goto error_remove_files; - } else if (data->type == smsc47m2) - dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n"); - - if (pwm1) { - err = sysfs_create_group(&dev->kobj, - &smsc47m1_group_pwm1); - if (err) - goto error_remove_files; - } else - dev_dbg(dev, "PWM 1 not enabled by hardware, skipping\n"); - - if (pwm2) { - err = sysfs_create_group(&dev->kobj, - &smsc47m1_group_pwm2); - if (err) - goto error_remove_files; - } else - dev_dbg(dev, "PWM 2 not enabled by hardware, skipping\n"); - - if (pwm3) { - err = sysfs_create_group(&dev->kobj, - &smsc47m1_group_pwm3); - if (err) - goto error_remove_files; - } else if (data->type == smsc47m2) - dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n"); - - err = sysfs_create_group(&dev->kobj, &smsc47m1_group); - if (err) - goto error_remove_files; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_remove_files; - } - - return 0; - -error_remove_files: - smsc47m1_remove_files(dev); -error_free: - platform_set_drvdata(pdev, NULL); - kfree(data); -error_release: - smsc47m1_handle_resources(res->start, sio_data->type, RELEASE, dev); - return err; -} - -static int __exit smsc47m1_remove(struct platform_device *pdev) -{ - struct smsc47m1_data *data = platform_get_drvdata(pdev); - struct resource *res; - - hwmon_device_unregister(data->hwmon_dev); - smsc47m1_remove_files(&pdev->dev); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - smsc47m1_handle_resources(res->start, data->type, RELEASE, &pdev->dev); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, - int init) -{ - struct smsc47m1_data *data = dev_get_drvdata(dev); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { - int i, fan_nr; - fan_nr = data->type == smsc47m2 ? 3 : 2; - - for (i = 0; i < fan_nr; i++) { - data->fan[i] = smsc47m1_read_value(data, - SMSC47M1_REG_FAN[i]); - data->fan_preload[i] = smsc47m1_read_value(data, - SMSC47M1_REG_FAN_PRELOAD[i]); - data->pwm[i] = smsc47m1_read_value(data, - SMSC47M1_REG_PWM[i]); - } - - i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - - data->alarms = smsc47m1_read_value(data, - SMSC47M1_REG_ALARM) >> 6; - /* Clear alarms if needed */ - if (data->alarms) - smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0); - - if (fan_nr >= 3) { - data->fan_div[2] = (smsc47m1_read_value(data, - SMSC47M2_REG_FANDIV3) >> 4) & 0x03; - data->alarms |= (smsc47m1_read_value(data, - SMSC47M2_REG_ALARM6) & 0x40) >> 4; - /* Clear alarm if needed */ - if (data->alarms & 0x04) - smsc47m1_write_value(data, - SMSC47M2_REG_ALARM6, - 0x40); - } - - data->last_updated = jiffies; - } - - mutex_unlock(&data->update_lock); - return data; -} - -static int __init smsc47m1_device_add(unsigned short address, - const struct smsc47m1_sio_data *sio_data) -{ - struct resource res = { - .start = address, - .end = address + SMSC_EXTENT - 1, - .name = DRVNAME, - .flags = IORESOURCE_IO, - }; - int err; - - err = smsc47m1_handle_resources(address, sio_data->type, CHECK, NULL); - if (err) - goto exit; - - pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add_data(pdev, sio_data, - sizeof(struct smsc47m1_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init sm_smsc47m1_init(void) -{ - int err; - unsigned short address; - struct smsc47m1_sio_data sio_data; - - err = smsc47m1_find(&sio_data); - if (err < 0) - return err; - address = err; - - /* Sets global pdev as a side effect */ - err = smsc47m1_device_add(address, &sio_data); - if (err) - return err; - - err = platform_driver_probe(&smsc47m1_driver, smsc47m1_probe); - if (err) - goto exit_device; - - return 0; - -exit_device: - platform_device_unregister(pdev); - smsc47m1_restore(&sio_data); - return err; -} - -static void __exit sm_smsc47m1_exit(void) -{ - platform_driver_unregister(&smsc47m1_driver); - smsc47m1_restore(pdev->dev.platform_data); - platform_device_unregister(pdev); -} - -MODULE_AUTHOR("Mark D. Studebaker "); -MODULE_DESCRIPTION("SMSC LPC47M1xx fan sensors driver"); -MODULE_LICENSE("GPL"); - -module_init(sm_smsc47m1_init); -module_exit(sm_smsc47m1_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/smsc47m192.c b/ANDROID_3.4.5/drivers/hwmon/smsc47m192.c deleted file mode 100644 index 4705a8bf..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/smsc47m192.c +++ /dev/null @@ -1,682 +0,0 @@ -/* - * smsc47m192.c - Support for hardware monitoring block of - * SMSC LPC47M192 and compatible Super I/O chips - * - * Copyright (C) 2006 Hartmut Rick - * - * Derived from lm78.c and other chip drivers. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END }; - -/* SMSC47M192 registers */ -#define SMSC47M192_REG_IN(nr) ((nr) < 6 ? (0x20 + (nr)) : \ - (0x50 + (nr) - 6)) -#define SMSC47M192_REG_IN_MAX(nr) ((nr) < 6 ? (0x2b + (nr) * 2) : \ - (0x54 + (((nr) - 6) * 2))) -#define SMSC47M192_REG_IN_MIN(nr) ((nr) < 6 ? (0x2c + (nr) * 2) : \ - (0x55 + (((nr) - 6) * 2))) -static u8 SMSC47M192_REG_TEMP[3] = { 0x27, 0x26, 0x52 }; -static u8 SMSC47M192_REG_TEMP_MAX[3] = { 0x39, 0x37, 0x58 }; -static u8 SMSC47M192_REG_TEMP_MIN[3] = { 0x3A, 0x38, 0x59 }; -#define SMSC47M192_REG_TEMP_OFFSET(nr) ((nr) == 2 ? 0x1e : 0x1f) -#define SMSC47M192_REG_ALARM1 0x41 -#define SMSC47M192_REG_ALARM2 0x42 -#define SMSC47M192_REG_VID 0x47 -#define SMSC47M192_REG_VID4 0x49 -#define SMSC47M192_REG_CONFIG 0x40 -#define SMSC47M192_REG_SFR 0x4f -#define SMSC47M192_REG_COMPANY_ID 0x3e -#define SMSC47M192_REG_VERSION 0x3f - -/* generalised scaling with integer rounding */ -static inline int SCALE(long val, int mul, int div) -{ - if (val < 0) - return (val * mul - div / 2) / div; - else - return (val * mul + div / 2) / div; -} - -/* Conversions */ - -/* smsc47m192 internally scales voltage measurements */ -static const u16 nom_mv[] = { 2500, 2250, 3300, 5000, 12000, 3300, 1500, 1800 }; - -static inline unsigned int IN_FROM_REG(u8 reg, int n) -{ - return SCALE(reg, nom_mv[n], 192); -} - -static inline u8 IN_TO_REG(unsigned long val, int n) -{ - return SENSORS_LIMIT(SCALE(val, 192, nom_mv[n]), 0, 255); -} - -/* - * TEMP: 0.001 degC units (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static inline s8 TEMP_TO_REG(int val) -{ - return SENSORS_LIMIT(SCALE(val, 1, 1000), -128000, 127000); -} - -static inline int TEMP_FROM_REG(s8 val) -{ - return val * 1000; -} - -struct smsc47m192_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[8]; /* Register value */ - u8 in_max[8]; /* Register value */ - u8 in_min[8]; /* Register value */ - s8 temp[3]; /* Register value */ - s8 temp_max[3]; /* Register value */ - s8 temp_min[3]; /* Register value */ - s8 temp_offset[3]; /* Register value */ - u16 alarms; /* Register encoding, combined */ - u8 vid; /* Register encoding, combined */ - u8 vrm; -}; - -static int smsc47m192_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int smsc47m192_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int smsc47m192_remove(struct i2c_client *client); -static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); - -static const struct i2c_device_id smsc47m192_id[] = { - { "smsc47m192", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, smsc47m192_id); - -static struct i2c_driver smsc47m192_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "smsc47m192", - }, - .probe = smsc47m192_probe, - .remove = smsc47m192_remove, - .id_table = smsc47m192_id, - .detect = smsc47m192_detect, - .address_list = normal_i2c, -}; - -/* Voltages */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr], nr)); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr], nr)); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr], nr)); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val, nr); - i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr), - data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val, nr); - i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr), - data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_in_offset(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); - -show_in_offset(0) -show_in_offset(1) -show_in_offset(2) -show_in_offset(3) -show_in_offset(4) -show_in_offset(5) -show_in_offset(6) -show_in_offset(7) - -/* Temperatures */ -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); -} - -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_min[nr])); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_max[nr])); -} - -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[nr] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr], - data->temp_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = TEMP_TO_REG(val); - i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr], - data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_offset(struct device *dev, struct device_attribute - *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_offset[nr])); -} - -static ssize_t set_temp_offset(struct device *dev, struct device_attribute - *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_offset[nr] = TEMP_TO_REG(val); - if (nr > 1) - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); - else if (data->temp_offset[nr] != 0) { - /* - * offset[0] and offset[1] share the same register, - * SFR bit 4 activates offset[0] - */ - i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, - (sfr & 0xef) | (nr == 0 ? 0x10 : 0)); - data->temp_offset[1-nr] = 0; - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_TEMP_OFFSET(nr), data->temp_offset[nr]); - } else if ((sfr & 0x10) == (nr == 0 ? 0x10 : 0)) - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_TEMP_OFFSET(nr), 0); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_temp_index(index) \ -static SENSOR_DEVICE_ATTR(temp##index##_input, S_IRUGO, \ - show_temp, NULL, index-1); \ -static SENSOR_DEVICE_ATTR(temp##index##_min, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, index-1); \ -static SENSOR_DEVICE_ATTR(temp##index##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, index-1); \ -static SENSOR_DEVICE_ATTR(temp##index##_offset, S_IRUGO | S_IWUSR, \ - show_temp_offset, set_temp_offset, index-1); - -show_temp_index(1) -show_temp_index(2) -show_temp_index(3) - -/* VID */ -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); - -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct smsc47m192_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct smsc47m192_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm); - -/* Alarms */ -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct smsc47m192_data *data = smsc47m192_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms & nr) ? 1 : 0); -} - -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 0x4000); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 0x8000); -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 0x0008); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 0x0100); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 0x0200); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 0x0400); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 0x0800); - -static struct attribute *smsc47m192_attributes[] = { - &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, - &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, - &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, - &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, - &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, - &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, - &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, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_offset.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_offset.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_offset.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - NULL -}; - -static const struct attribute_group smsc47m192_group = { - .attrs = smsc47m192_attributes, -}; - -static struct attribute *smsc47m192_attributes_in4[] = { - &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 -}; - -static const struct attribute_group smsc47m192_group_in4 = { - .attrs = smsc47m192_attributes_in4, -}; - -static void smsc47m192_init_client(struct i2c_client *client) -{ - int i; - u8 config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); - u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); - - /* select cycle mode (pause 1 sec between updates) */ - i2c_smbus_write_byte_data(client, SMSC47M192_REG_SFR, - (sfr & 0xfd) | 0x02); - if (!(config & 0x01)) { - /* initialize alarm limits */ - for (i = 0; i < 8; i++) { - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_IN_MIN(i), 0); - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_IN_MAX(i), 0xff); - } - for (i = 0; i < 3; i++) { - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_TEMP_MIN[i], 0x80); - i2c_smbus_write_byte_data(client, - SMSC47M192_REG_TEMP_MAX[i], 0x7f); - } - - /* start monitoring */ - i2c_smbus_write_byte_data(client, SMSC47M192_REG_CONFIG, - (config & 0xf7) | 0x01); - } -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int smsc47m192_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int version; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Detection criteria from sensors_detect script */ - version = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VERSION); - if (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_COMPANY_ID) == 0x55 - && (version & 0xf0) == 0x20 - && (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_VID) & 0x70) == 0x00 - && (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_VID4) & 0xfe) == 0x80) { - dev_info(&adapter->dev, - "found SMSC47M192 or compatible, " - "version 2, stepping A%d\n", version & 0x0f); - } else { - dev_dbg(&adapter->dev, - "SMSC47M192 detection failed at 0x%02x\n", - client->addr); - return -ENODEV; - } - - strlcpy(info->type, "smsc47m192", I2C_NAME_SIZE); - - return 0; -} - -static int smsc47m192_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct smsc47m192_data *data; - int config; - int err; - - data = kzalloc(sizeof(struct smsc47m192_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->vrm = vid_which_vrm(); - mutex_init(&data->update_lock); - - /* Initialize the SMSC47M192 chip */ - smsc47m192_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group); - if (err) - goto exit_free; - - /* Pin 110 is either in4 (+12V) or VID4 */ - config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); - if (!(config & 0x20)) { - err = sysfs_create_group(&client->dev.kobj, - &smsc47m192_group_in4); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); -exit_free: - kfree(data); -exit: - return err; -} - -static int smsc47m192_remove(struct i2c_client *client) -{ - struct smsc47m192_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); - - kfree(data); - - return 0; -} - -static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - int i, config; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); - - dev_dbg(&client->dev, "Starting smsc47m192 update\n"); - - for (i = 0; i <= 7; i++) { - data->in[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_IN(i)); - data->in_min[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_IN_MIN(i)); - data->in_max[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_IN_MAX(i)); - } - for (i = 0; i < 3; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP[i]); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP_MAX[i]); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP_MIN[i]); - } - for (i = 1; i < 3; i++) - data->temp_offset[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP_OFFSET(i)); - /* - * first offset is temp_offset[0] if SFR bit 4 is set, - * temp_offset[1] otherwise - */ - if (sfr & 0x10) { - data->temp_offset[0] = data->temp_offset[1]; - data->temp_offset[1] = 0; - } else - data->temp_offset[0] = 0; - - data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) - & 0x0f; - config = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_CONFIG); - if (config & 0x20) - data->vid |= (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_VID4) & 0x01) << 4; - data->alarms = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_ALARM1) | - (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_ALARM2) << 8); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(smsc47m192_driver); - -MODULE_AUTHOR("Hartmut Rick "); -MODULE_DESCRIPTION("SMSC47M192 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/thmc50.c b/ANDROID_3.4.5/drivers/hwmon/thmc50.c deleted file mode 100644 index add9f019..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/thmc50.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * thmc50.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2007 Krzysztof Helt - * Based on 2.4 driver by Frodo Looijaard and - * Philip Edelbrock - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END }; - -/* Insmod parameters */ -enum chips { thmc50, adm1022 }; - -static unsigned short adm1022_temp3[16]; -static unsigned int adm1022_temp3_num; -module_param_array(adm1022_temp3, ushort, &adm1022_temp3_num, 0); -MODULE_PARM_DESC(adm1022_temp3, "List of adapter,address pairs " - "to enable 3rd temperature (ADM1022 only)"); - -/* Many THMC50 constants specified below */ - -/* The THMC50 registers */ -#define THMC50_REG_CONF 0x40 -#define THMC50_REG_COMPANY_ID 0x3E -#define THMC50_REG_DIE_CODE 0x3F -#define THMC50_REG_ANALOG_OUT 0x19 -/* - * The mirror status register cannot be used as - * reading it does not clear alarms. - */ -#define THMC50_REG_INTR 0x41 - -static const u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 }; -static const u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C }; -static const u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B }; -static const u8 THMC50_REG_TEMP_CRITICAL[] = { 0x13, 0x14, 0x14 }; -static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 }; - -#define THMC50_REG_CONF_nFANOFF 0x20 -#define THMC50_REG_CONF_PROGRAMMED 0x08 - -/* Each client has this additional data */ -struct thmc50_data { - struct device *hwmon_dev; - - struct mutex update_lock; - enum chips type; - unsigned long last_updated; /* In jiffies */ - char has_temp3; /* !=0 if it is ADM1022 in temp3 mode */ - char valid; /* !=0 if following fields are valid */ - - /* Register values */ - s8 temp_input[3]; - s8 temp_max[3]; - s8 temp_min[3]; - s8 temp_critical[3]; - u8 analog_out; - u8 alarms; -}; - -static int thmc50_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int thmc50_remove(struct i2c_client *client); -static void thmc50_init_client(struct i2c_client *client); -static struct thmc50_data *thmc50_update_device(struct device *dev); - -static const struct i2c_device_id thmc50_id[] = { - { "adm1022", adm1022 }, - { "thmc50", thmc50 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, thmc50_id); - -static struct i2c_driver thmc50_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "thmc50", - }, - .probe = thmc50_probe, - .remove = thmc50_remove, - .id_table = thmc50_id, - .detect = thmc50_detect, - .address_list = normal_i2c, -}; - -static ssize_t show_analog_out(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct thmc50_data *data = thmc50_update_device(dev); - return sprintf(buf, "%d\n", data->analog_out); -} - -static ssize_t set_analog_out(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); - int config; - unsigned long tmp; - int err; - - err = kstrtoul(buf, 10, &tmp); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->analog_out = SENSORS_LIMIT(tmp, 0, 255); - i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, - data->analog_out); - - config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); - if (data->analog_out == 0) - config &= ~THMC50_REG_CONF_nFANOFF; - else - config |= THMC50_REG_CONF_nFANOFF; - i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); - - mutex_unlock(&data->update_lock); - return count; -} - -/* There is only one PWM mode = DC */ -static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "0\n"); -} - -/* Temperatures */ -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct thmc50_data *data = thmc50_update_device(dev); - return sprintf(buf, "%d\n", data->temp_input[nr] * 1000); -} - -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct thmc50_data *data = thmc50_update_device(dev); - return sprintf(buf, "%d\n", data->temp_min[nr] * 1000); -} - -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[nr] = SENSORS_LIMIT(val / 1000, -128, 127); - i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MIN[nr], - data->temp_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct thmc50_data *data = thmc50_update_device(dev); - return sprintf(buf, "%d\n", data->temp_max[nr] * 1000); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = SENSORS_LIMIT(val / 1000, -128, 127); - i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MAX[nr], - data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp_critical(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct thmc50_data *data = thmc50_update_device(dev); - return sprintf(buf, "%d\n", data->temp_critical[nr] * 1000); -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct thmc50_data *data = thmc50_update_device(dev); - - return sprintf(buf, "%u\n", (data->alarms >> index) & 1); -} - -#define temp_reg(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp, \ - NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IRUGO, \ - show_temp_critical, NULL, offset - 1); - -temp_reg(1); -temp_reg(2); -temp_reg(3); - -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2); - -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_analog_out, - set_analog_out, 0); -static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0); - -static struct attribute *thmc50_attributes[] = { - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_min.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_crit.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_min.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_crit.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm1_mode.dev_attr.attr, - NULL -}; - -static const struct attribute_group thmc50_group = { - .attrs = thmc50_attributes, -}; - -/* for ADM1022 3rd temperature mode */ -static struct attribute *temp3_attributes[] = { - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_min.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_crit.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - NULL -}; - -static const struct attribute_group temp3_group = { - .attrs = temp3_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int thmc50_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - unsigned company; - unsigned revision; - unsigned config; - struct i2c_adapter *adapter = client->adapter; - const char *type_name; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) { - pr_debug("thmc50: detect failed, " - "smbus byte data not supported!\n"); - return -ENODEV; - } - - pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n", - client->addr, i2c_adapter_id(client->adapter)); - - company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID); - revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE); - config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); - if (revision < 0xc0 || (config & 0x10)) - return -ENODEV; - - if (company == 0x41) { - int id = i2c_adapter_id(client->adapter); - int i; - - type_name = "adm1022"; - for (i = 0; i + 1 < adm1022_temp3_num; i += 2) - if (adm1022_temp3[i] == id && - adm1022_temp3[i + 1] == client->addr) { - /* enable 2nd remote temp */ - config |= (1 << 7); - i2c_smbus_write_byte_data(client, - THMC50_REG_CONF, - config); - break; - } - } else if (company == 0x49) { - type_name = "thmc50"; - } else { - pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n"); - return -ENODEV; - } - - pr_debug("thmc50: Detected %s (version %x, revision %x)\n", - type_name, (revision >> 4) - 0xc, revision & 0xf); - - strlcpy(info->type, type_name, I2C_NAME_SIZE); - - return 0; -} - -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct thmc50_data *data; - int err; - - data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL); - if (!data) { - pr_debug("thmc50: detect failed, kzalloc failed!\n"); - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - mutex_init(&data->update_lock); - - thmc50_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &thmc50_group); - if (err) - goto exit_free; - - /* Register ADM1022 sysfs hooks */ - if (data->has_temp3) { - err = sysfs_create_group(&client->dev.kobj, &temp3_group); - if (err) - goto exit_remove_sysfs_thmc50; - } - - /* Register a new directory entry with module sensors */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_sysfs; - } - - return 0; - -exit_remove_sysfs: - if (data->has_temp3) - sysfs_remove_group(&client->dev.kobj, &temp3_group); -exit_remove_sysfs_thmc50: - sysfs_remove_group(&client->dev.kobj, &thmc50_group); -exit_free: - kfree(data); -exit: - return err; -} - -static int thmc50_remove(struct i2c_client *client) -{ - struct thmc50_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &thmc50_group); - if (data->has_temp3) - sysfs_remove_group(&client->dev.kobj, &temp3_group); - - kfree(data); - - return 0; -} - -static void thmc50_init_client(struct i2c_client *client) -{ - struct thmc50_data *data = i2c_get_clientdata(client); - int config; - - data->analog_out = i2c_smbus_read_byte_data(client, - THMC50_REG_ANALOG_OUT); - /* set up to at least 1 */ - if (data->analog_out == 0) { - data->analog_out = 1; - i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT, - data->analog_out); - } - config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); - config |= 0x1; /* start the chip if it is in standby mode */ - if (data->type == adm1022 && (config & (1 << 7))) - data->has_temp3 = 1; - i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); -} - -static struct thmc50_data *thmc50_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); - int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + timeout) - || !data->valid) { - - int temps = data->has_temp3 ? 3 : 2; - int i; - int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); - - prog &= THMC50_REG_CONF_PROGRAMMED; - - for (i = 0; i < temps; i++) { - data->temp_input[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP[i]); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP_MAX[i]); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP_MIN[i]); - data->temp_critical[i] = - i2c_smbus_read_byte_data(client, - prog ? THMC50_REG_TEMP_CRITICAL[i] - : THMC50_REG_TEMP_DEFAULT[i]); - } - data->analog_out = - i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); - data->alarms = - i2c_smbus_read_byte_data(client, THMC50_REG_INTR); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(thmc50_driver); - -MODULE_AUTHOR("Krzysztof Helt "); -MODULE_DESCRIPTION("THMC50 driver"); diff --git a/ANDROID_3.4.5/drivers/hwmon/tmp102.c b/ANDROID_3.4.5/drivers/hwmon/tmp102.c deleted file mode 100644 index 0d466b9d..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/tmp102.c +++ /dev/null @@ -1,299 +0,0 @@ -/* Texas Instruments TMP102 SMBus temperature sensor driver - * - * Copyright (C) 2010 Steven King - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "tmp102" - -#define TMP102_TEMP_REG 0x00 -#define TMP102_CONF_REG 0x01 -/* note: these bit definitions are byte swapped */ -#define TMP102_CONF_SD 0x0100 -#define TMP102_CONF_TM 0x0200 -#define TMP102_CONF_POL 0x0400 -#define TMP102_CONF_F0 0x0800 -#define TMP102_CONF_F1 0x1000 -#define TMP102_CONF_R0 0x2000 -#define TMP102_CONF_R1 0x4000 -#define TMP102_CONF_OS 0x8000 -#define TMP102_CONF_EM 0x0010 -#define TMP102_CONF_AL 0x0020 -#define TMP102_CONF_CR0 0x0040 -#define TMP102_CONF_CR1 0x0080 -#define TMP102_TLOW_REG 0x02 -#define TMP102_THIGH_REG 0x03 - -struct tmp102 { - struct device *hwmon_dev; - struct mutex lock; - u16 config_orig; - unsigned long last_update; - int temp[3]; -}; - -/* convert left adjusted 13-bit TMP102 register value to milliCelsius */ -static inline int tmp102_reg_to_mC(s16 val) -{ - return ((val & ~0x01) * 1000) / 128; -} - -/* convert milliCelsius to left adjusted 13-bit TMP102 register value */ -static inline u16 tmp102_mC_to_reg(int val) -{ - return (val * 128) / 1000; -} - -static const u8 tmp102_reg[] = { - TMP102_TEMP_REG, - TMP102_TLOW_REG, - TMP102_THIGH_REG, -}; - -static struct tmp102 *tmp102_update_device(struct i2c_client *client) -{ - struct tmp102 *tmp102 = i2c_get_clientdata(client); - - mutex_lock(&tmp102->lock); - if (time_after(jiffies, tmp102->last_update + HZ / 3)) { - int i; - for (i = 0; i < ARRAY_SIZE(tmp102->temp); ++i) { - int status = i2c_smbus_read_word_swapped(client, - tmp102_reg[i]); - if (status > -1) - tmp102->temp[i] = tmp102_reg_to_mC(status); - } - tmp102->last_update = jiffies; - } - mutex_unlock(&tmp102->lock); - return tmp102; -} - -static ssize_t tmp102_show_temp(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev)); - - return sprintf(buf, "%d\n", tmp102->temp[sda->index]); -} - -static ssize_t tmp102_set_temp(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct tmp102 *tmp102 = i2c_get_clientdata(client); - long val; - int status; - - if (kstrtol(buf, 10, &val) < 0) - return -EINVAL; - val = SENSORS_LIMIT(val, -256000, 255000); - - mutex_lock(&tmp102->lock); - tmp102->temp[sda->index] = val; - status = i2c_smbus_write_word_swapped(client, tmp102_reg[sda->index], - tmp102_mC_to_reg(val)); - mutex_unlock(&tmp102->lock); - return status ? : count; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp102_show_temp, NULL , 0); - -static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, - tmp102_set_temp, 1); - -static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, - tmp102_set_temp, 2); - -static struct attribute *tmp102_attributes[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - NULL -}; - -static const struct attribute_group tmp102_attr_group = { - .attrs = tmp102_attributes, -}; - -#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) -#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) - -static int __devinit tmp102_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct tmp102 *tmp102; - int status; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_WORD_DATA)) { - dev_err(&client->dev, "adapter doesn't support SMBus word " - "transactions\n"); - return -ENODEV; - } - - tmp102 = kzalloc(sizeof(*tmp102), GFP_KERNEL); - if (!tmp102) { - dev_dbg(&client->dev, "kzalloc failed\n"); - return -ENOMEM; - } - i2c_set_clientdata(client, tmp102); - - status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); - if (status < 0) { - dev_err(&client->dev, "error reading config register\n"); - goto fail_free; - } - tmp102->config_orig = status; - status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, - TMP102_CONFIG); - if (status < 0) { - dev_err(&client->dev, "error writing config register\n"); - goto fail_restore_config; - } - status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); - if (status < 0) { - dev_err(&client->dev, "error reading config register\n"); - goto fail_restore_config; - } - status &= ~TMP102_CONFIG_RD_ONLY; - if (status != TMP102_CONFIG) { - dev_err(&client->dev, "config settings did not stick\n"); - status = -ENODEV; - goto fail_restore_config; - } - tmp102->last_update = jiffies - HZ; - mutex_init(&tmp102->lock); - - status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group); - if (status) { - dev_dbg(&client->dev, "could not create sysfs files\n"); - goto fail_restore_config; - } - tmp102->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(tmp102->hwmon_dev)) { - dev_dbg(&client->dev, "unable to register hwmon device\n"); - status = PTR_ERR(tmp102->hwmon_dev); - goto fail_remove_sysfs; - } - - dev_info(&client->dev, "initialized\n"); - - return 0; - -fail_remove_sysfs: - sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); -fail_restore_config: - i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, - tmp102->config_orig); -fail_free: - kfree(tmp102); - - return status; -} - -static int __devexit tmp102_remove(struct i2c_client *client) -{ - struct tmp102 *tmp102 = i2c_get_clientdata(client); - - hwmon_device_unregister(tmp102->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group); - - /* Stop monitoring if device was stopped originally */ - if (tmp102->config_orig & TMP102_CONF_SD) { - int config; - - config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); - if (config >= 0) - i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, - config | TMP102_CONF_SD); - } - - kfree(tmp102); - - return 0; -} - -#ifdef CONFIG_PM -static int tmp102_suspend(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - int config; - - config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); - if (config < 0) - return config; - - config |= TMP102_CONF_SD; - return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); -} - -static int tmp102_resume(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - int config; - - config = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); - if (config < 0) - return config; - - config &= ~TMP102_CONF_SD; - return i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, config); -} - -static const struct dev_pm_ops tmp102_dev_pm_ops = { - .suspend = tmp102_suspend, - .resume = tmp102_resume, -}; - -#define TMP102_DEV_PM_OPS (&tmp102_dev_pm_ops) -#else -#define TMP102_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - -static const struct i2c_device_id tmp102_id[] = { - { "tmp102", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tmp102_id); - -static struct i2c_driver tmp102_driver = { - .driver.name = DRIVER_NAME, - .driver.pm = TMP102_DEV_PM_OPS, - .probe = tmp102_probe, - .remove = __devexit_p(tmp102_remove), - .id_table = tmp102_id, -}; - -module_i2c_driver(tmp102_driver); - -MODULE_AUTHOR("Steven King "); -MODULE_DESCRIPTION("Texas Instruments TMP102 temperature sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/tmp401.c b/ANDROID_3.4.5/drivers/hwmon/tmp401.c deleted file mode 100644 index ea54c338..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/tmp401.c +++ /dev/null @@ -1,669 +0,0 @@ -/* tmp401.c - * - * Copyright (C) 2007,2008 Hans de Goede - * Preliminary tmp411 support by: - * Gabriel Konat, Sander Leget, Wouter Willems - * Copyright (C) 2009 Andre Prendel - * - * 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. - */ - -/* - * Driver for the Texas Instruments TMP401 SMBUS temperature sensor IC. - * - * Note this IC is in some aspect similar to the LM90, but it has quite a - * few differences too, for example the local temp has a higher resolution - * and thus has 16 bits registers for its value and limit instead of 8 bits. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x4c, I2C_CLIENT_END }; - -enum chips { tmp401, tmp411 }; - -/* - * The TMP401 registers, note some registers have different addresses for - * reading and writing - */ -#define TMP401_STATUS 0x02 -#define TMP401_CONFIG_READ 0x03 -#define TMP401_CONFIG_WRITE 0x09 -#define TMP401_CONVERSION_RATE_READ 0x04 -#define TMP401_CONVERSION_RATE_WRITE 0x0A -#define TMP401_TEMP_CRIT_HYST 0x21 -#define TMP401_CONSECUTIVE_ALERT 0x22 -#define TMP401_MANUFACTURER_ID_REG 0xFE -#define TMP401_DEVICE_ID_REG 0xFF -#define TMP411_N_FACTOR_REG 0x18 - -static const u8 TMP401_TEMP_MSB[2] = { 0x00, 0x01 }; -static const u8 TMP401_TEMP_LSB[2] = { 0x15, 0x10 }; -static const u8 TMP401_TEMP_LOW_LIMIT_MSB_READ[2] = { 0x06, 0x08 }; -static const u8 TMP401_TEMP_LOW_LIMIT_MSB_WRITE[2] = { 0x0C, 0x0E }; -static const u8 TMP401_TEMP_LOW_LIMIT_LSB[2] = { 0x17, 0x14 }; -static const u8 TMP401_TEMP_HIGH_LIMIT_MSB_READ[2] = { 0x05, 0x07 }; -static const u8 TMP401_TEMP_HIGH_LIMIT_MSB_WRITE[2] = { 0x0B, 0x0D }; -static const u8 TMP401_TEMP_HIGH_LIMIT_LSB[2] = { 0x16, 0x13 }; -/* These are called the THERM limit / hysteresis / mask in the datasheet */ -static const u8 TMP401_TEMP_CRIT_LIMIT[2] = { 0x20, 0x19 }; - -static const u8 TMP411_TEMP_LOWEST_MSB[2] = { 0x30, 0x34 }; -static const u8 TMP411_TEMP_LOWEST_LSB[2] = { 0x31, 0x35 }; -static const u8 TMP411_TEMP_HIGHEST_MSB[2] = { 0x32, 0x36 }; -static const u8 TMP411_TEMP_HIGHEST_LSB[2] = { 0x33, 0x37 }; - -/* Flags */ -#define TMP401_CONFIG_RANGE 0x04 -#define TMP401_CONFIG_SHUTDOWN 0x40 -#define TMP401_STATUS_LOCAL_CRIT 0x01 -#define TMP401_STATUS_REMOTE_CRIT 0x02 -#define TMP401_STATUS_REMOTE_OPEN 0x04 -#define TMP401_STATUS_REMOTE_LOW 0x08 -#define TMP401_STATUS_REMOTE_HIGH 0x10 -#define TMP401_STATUS_LOCAL_LOW 0x20 -#define TMP401_STATUS_LOCAL_HIGH 0x40 - -/* Manufacturer / Device ID's */ -#define TMP401_MANUFACTURER_ID 0x55 -#define TMP401_DEVICE_ID 0x11 -#define TMP411_DEVICE_ID 0x12 - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id tmp401_id[] = { - { "tmp401", tmp401 }, - { "tmp411", tmp411 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tmp401_id); - -/* - * Client data (each client gets its own) - */ - -struct tmp401_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - enum chips kind; - - /* register values */ - u8 status; - u8 config; - u16 temp[2]; - u16 temp_low[2]; - u16 temp_high[2]; - u8 temp_crit[2]; - u8 temp_crit_hyst; - u16 temp_lowest[2]; - u16 temp_highest[2]; -}; - -/* - * Sysfs attr show / store functions - */ - -static int tmp401_register_to_temp(u16 reg, u8 config) -{ - int temp = reg; - - if (config & TMP401_CONFIG_RANGE) - temp -= 64 * 256; - - return (temp * 625 + 80) / 160; -} - -static u16 tmp401_temp_to_register(long temp, u8 config) -{ - if (config & TMP401_CONFIG_RANGE) { - temp = SENSORS_LIMIT(temp, -64000, 191000); - temp += 64000; - } else - temp = SENSORS_LIMIT(temp, 0, 127000); - - return (temp * 160 + 312) / 625; -} - -static int tmp401_crit_register_to_temp(u8 reg, u8 config) -{ - int temp = reg; - - if (config & TMP401_CONFIG_RANGE) - temp -= 64; - - return temp * 1000; -} - -static u8 tmp401_crit_temp_to_register(long temp, u8 config) -{ - if (config & TMP401_CONFIG_RANGE) { - temp = SENSORS_LIMIT(temp, -64000, 191000); - temp += 64000; - } else - temp = SENSORS_LIMIT(temp, 0, 127000); - - return (temp + 500) / 1000; -} - -static struct tmp401_data *tmp401_update_device_reg16( - struct i2c_client *client, struct tmp401_data *data) -{ - int i; - - for (i = 0; i < 2; i++) { - /* - * High byte must be read first immediately followed - * by the low byte - */ - data->temp[i] = i2c_smbus_read_byte_data(client, - TMP401_TEMP_MSB[i]) << 8; - data->temp[i] |= i2c_smbus_read_byte_data(client, - TMP401_TEMP_LSB[i]); - data->temp_low[i] = i2c_smbus_read_byte_data(client, - TMP401_TEMP_LOW_LIMIT_MSB_READ[i]) << 8; - data->temp_low[i] |= i2c_smbus_read_byte_data(client, - TMP401_TEMP_LOW_LIMIT_LSB[i]); - data->temp_high[i] = i2c_smbus_read_byte_data(client, - TMP401_TEMP_HIGH_LIMIT_MSB_READ[i]) << 8; - data->temp_high[i] |= i2c_smbus_read_byte_data(client, - TMP401_TEMP_HIGH_LIMIT_LSB[i]); - data->temp_crit[i] = i2c_smbus_read_byte_data(client, - TMP401_TEMP_CRIT_LIMIT[i]); - - if (data->kind == tmp411) { - data->temp_lowest[i] = i2c_smbus_read_byte_data(client, - TMP411_TEMP_LOWEST_MSB[i]) << 8; - data->temp_lowest[i] |= i2c_smbus_read_byte_data( - client, TMP411_TEMP_LOWEST_LSB[i]); - - data->temp_highest[i] = i2c_smbus_read_byte_data( - client, TMP411_TEMP_HIGHEST_MSB[i]) << 8; - data->temp_highest[i] |= i2c_smbus_read_byte_data( - client, TMP411_TEMP_HIGHEST_LSB[i]); - } - } - return data; -} - -static struct tmp401_data *tmp401_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tmp401_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - data->status = i2c_smbus_read_byte_data(client, TMP401_STATUS); - data->config = i2c_smbus_read_byte_data(client, - TMP401_CONFIG_READ); - tmp401_update_device_reg16(client, data); - - data->temp_crit_hyst = i2c_smbus_read_byte_data(client, - TMP401_TEMP_CRIT_HYST); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static ssize_t show_temp_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - return sprintf(buf, "%d\n", - tmp401_register_to_temp(data->temp[index], data->config)); -} - -static ssize_t show_temp_min(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - return sprintf(buf, "%d\n", - tmp401_register_to_temp(data->temp_low[index], data->config)); -} - -static ssize_t show_temp_max(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - return sprintf(buf, "%d\n", - tmp401_register_to_temp(data->temp_high[index], data->config)); -} - -static ssize_t show_temp_crit(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - return sprintf(buf, "%d\n", - tmp401_crit_register_to_temp(data->temp_crit[index], - data->config)); -} - -static ssize_t show_temp_crit_hyst(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int temp, index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - mutex_lock(&data->update_lock); - temp = tmp401_crit_register_to_temp(data->temp_crit[index], - data->config); - temp -= data->temp_crit_hyst * 1000; - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", temp); -} - -static ssize_t show_temp_lowest(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - return sprintf(buf, "%d\n", - tmp401_register_to_temp(data->temp_lowest[index], - data->config)); -} - -static ssize_t show_temp_highest(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - return sprintf(buf, "%d\n", - tmp401_register_to_temp(data->temp_highest[index], - data->config)); -} - -static ssize_t show_status(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int mask = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - - if (data->status & mask) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static ssize_t store_temp_min(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - long val; - u16 reg; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - reg = tmp401_temp_to_register(val, data->config); - - mutex_lock(&data->update_lock); - - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP401_TEMP_LOW_LIMIT_MSB_WRITE[index], reg >> 8); - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP401_TEMP_LOW_LIMIT_LSB[index], reg & 0xFF); - - data->temp_low[index] = reg; - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t store_temp_max(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - long val; - u16 reg; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - reg = tmp401_temp_to_register(val, data->config); - - mutex_lock(&data->update_lock); - - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP401_TEMP_HIGH_LIMIT_MSB_WRITE[index], reg >> 8); - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP401_TEMP_HIGH_LIMIT_LSB[index], reg & 0xFF); - - data->temp_high[index] = reg; - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t store_temp_crit(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - long val; - u8 reg; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - reg = tmp401_crit_temp_to_register(val, data->config); - - mutex_lock(&data->update_lock); - - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP401_TEMP_CRIT_LIMIT[index], reg); - - data->temp_crit[index] = reg; - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t store_temp_crit_hyst(struct device *dev, struct device_attribute - *devattr, const char *buf, size_t count) -{ - int temp, index = to_sensor_dev_attr(devattr)->index; - struct tmp401_data *data = tmp401_update_device(dev); - long val; - u8 reg; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - if (data->config & TMP401_CONFIG_RANGE) - val = SENSORS_LIMIT(val, -64000, 191000); - else - val = SENSORS_LIMIT(val, 0, 127000); - - mutex_lock(&data->update_lock); - temp = tmp401_crit_register_to_temp(data->temp_crit[index], - data->config); - val = SENSORS_LIMIT(val, temp - 255000, temp); - reg = ((temp - val) + 500) / 1000; - - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP401_TEMP_CRIT_HYST, reg); - - data->temp_crit_hyst = reg; - - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * Resets the historical measurements of minimum and maximum temperatures. - * This is done by writing any value to any of the minimum/maximum registers - * (0x30-0x37). - */ -static ssize_t reset_temp_history(struct device *dev, - struct device_attribute *devattr, const char *buf, size_t count) -{ - long val; - - if (kstrtol(buf, 10, &val)) - return -EINVAL; - - if (val != 1) { - dev_err(dev, "temp_reset_history value %ld not" - " supported. Use 1 to reset the history!\n", val); - return -EINVAL; - } - i2c_smbus_write_byte_data(to_i2c_client(dev), - TMP411_TEMP_LOWEST_MSB[0], val); - - return count; -} - -static struct sensor_device_attribute tmp401_attr[] = { - SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0), - SENSOR_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min, - store_temp_min, 0), - SENSOR_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, - store_temp_max, 0), - SENSOR_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit, - store_temp_crit, 0), - SENSOR_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temp_crit_hyst, - store_temp_crit_hyst, 0), - SENSOR_ATTR(temp1_min_alarm, S_IRUGO, show_status, NULL, - TMP401_STATUS_LOCAL_LOW), - SENSOR_ATTR(temp1_max_alarm, S_IRUGO, show_status, NULL, - TMP401_STATUS_LOCAL_HIGH), - SENSOR_ATTR(temp1_crit_alarm, S_IRUGO, show_status, NULL, - TMP401_STATUS_LOCAL_CRIT), - SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1), - SENSOR_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min, - store_temp_min, 1), - SENSOR_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max, - store_temp_max, 1), - SENSOR_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit, - store_temp_crit, 1), - SENSOR_ATTR(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL, 1), - SENSOR_ATTR(temp2_fault, S_IRUGO, show_status, NULL, - TMP401_STATUS_REMOTE_OPEN), - SENSOR_ATTR(temp2_min_alarm, S_IRUGO, show_status, NULL, - TMP401_STATUS_REMOTE_LOW), - SENSOR_ATTR(temp2_max_alarm, S_IRUGO, show_status, NULL, - TMP401_STATUS_REMOTE_HIGH), - SENSOR_ATTR(temp2_crit_alarm, S_IRUGO, show_status, NULL, - TMP401_STATUS_REMOTE_CRIT), -}; - -/* - * Additional features of the TMP411 chip. - * The TMP411 stores the minimum and maximum - * temperature measured since power-on, chip-reset, or - * minimum and maximum register reset for both the local - * and remote channels. - */ -static struct sensor_device_attribute tmp411_attr[] = { - SENSOR_ATTR(temp1_highest, S_IRUGO, show_temp_highest, NULL, 0), - SENSOR_ATTR(temp1_lowest, S_IRUGO, show_temp_lowest, NULL, 0), - SENSOR_ATTR(temp2_highest, S_IRUGO, show_temp_highest, NULL, 1), - SENSOR_ATTR(temp2_lowest, S_IRUGO, show_temp_lowest, NULL, 1), - SENSOR_ATTR(temp_reset_history, S_IWUSR, NULL, reset_temp_history, 0), -}; - -/* - * Begin non sysfs callback code (aka Real code) - */ - -static void tmp401_init_client(struct i2c_client *client) -{ - int config, config_orig; - - /* Set the conversion rate to 2 Hz */ - i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5); - - /* Start conversions (disable shutdown if necessary) */ - config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); - if (config < 0) { - dev_warn(&client->dev, "Initialization failed!\n"); - return; - } - - config_orig = config; - config &= ~TMP401_CONFIG_SHUTDOWN; - - if (config != config_orig) - i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config); -} - -static int tmp401_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - enum chips kind; - struct i2c_adapter *adapter = client->adapter; - u8 reg; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Detect and identify the chip */ - reg = i2c_smbus_read_byte_data(client, TMP401_MANUFACTURER_ID_REG); - if (reg != TMP401_MANUFACTURER_ID) - return -ENODEV; - - reg = i2c_smbus_read_byte_data(client, TMP401_DEVICE_ID_REG); - - switch (reg) { - case TMP401_DEVICE_ID: - kind = tmp401; - break; - case TMP411_DEVICE_ID: - kind = tmp411; - break; - default: - return -ENODEV; - } - - reg = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); - if (reg & 0x1b) - return -ENODEV; - - reg = i2c_smbus_read_byte_data(client, TMP401_CONVERSION_RATE_READ); - /* Datasheet says: 0x1-0x6 */ - if (reg > 15) - return -ENODEV; - - strlcpy(info->type, tmp401_id[kind].name, I2C_NAME_SIZE); - - return 0; -} - -static int tmp401_remove(struct i2c_client *client) -{ - struct tmp401_data *data = i2c_get_clientdata(client); - int i; - - if (data->hwmon_dev) - hwmon_device_unregister(data->hwmon_dev); - - for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) - device_remove_file(&client->dev, &tmp401_attr[i].dev_attr); - - if (data->kind == tmp411) { - for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) - device_remove_file(&client->dev, - &tmp411_attr[i].dev_attr); - } - - kfree(data); - return 0; -} - -static int tmp401_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int i, err = 0; - struct tmp401_data *data; - const char *names[] = { "TMP401", "TMP411" }; - - data = kzalloc(sizeof(struct tmp401_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->kind = id->driver_data; - - /* Initialize the TMP401 chip */ - tmp401_init_client(client); - - /* Register sysfs hooks */ - for (i = 0; i < ARRAY_SIZE(tmp401_attr); i++) { - err = device_create_file(&client->dev, - &tmp401_attr[i].dev_attr); - if (err) - goto exit_remove; - } - - /* Register additional tmp411 sysfs hooks */ - if (data->kind == tmp411) { - for (i = 0; i < ARRAY_SIZE(tmp411_attr); i++) { - err = device_create_file(&client->dev, - &tmp411_attr[i].dev_attr); - if (err) - goto exit_remove; - } - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - data->hwmon_dev = NULL; - goto exit_remove; - } - - dev_info(&client->dev, "Detected TI %s chip\n", names[data->kind]); - - return 0; - -exit_remove: - tmp401_remove(client); /* will also free data for us */ - return err; -} - -static struct i2c_driver tmp401_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "tmp401", - }, - .probe = tmp401_probe, - .remove = tmp401_remove, - .id_table = tmp401_id, - .detect = tmp401_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(tmp401_driver); - -MODULE_AUTHOR("Hans de Goede "); -MODULE_DESCRIPTION("Texas Instruments TMP401 temperature sensor driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/tmp421.c b/ANDROID_3.4.5/drivers/hwmon/tmp421.c deleted file mode 100644 index 8fac87a3..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/tmp421.c +++ /dev/null @@ -1,332 +0,0 @@ -/* tmp421.c - * - * Copyright (C) 2009 Andre Prendel - * Preliminary support by: - * Melvin Rook, Raymond Ng - * - * 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. - */ - -/* - * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC. - * Supported models: TMP421, TMP422, TMP423 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, - I2C_CLIENT_END }; - -enum chips { tmp421, tmp422, tmp423 }; - -/* The TMP421 registers */ -#define TMP421_CONFIG_REG_1 0x09 -#define TMP421_CONVERSION_RATE_REG 0x0B -#define TMP421_MANUFACTURER_ID_REG 0xFE -#define TMP421_DEVICE_ID_REG 0xFF - -static const u8 TMP421_TEMP_MSB[4] = { 0x00, 0x01, 0x02, 0x03 }; -static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 }; - -/* Flags */ -#define TMP421_CONFIG_SHUTDOWN 0x40 -#define TMP421_CONFIG_RANGE 0x04 - -/* Manufacturer / Device ID's */ -#define TMP421_MANUFACTURER_ID 0x55 -#define TMP421_DEVICE_ID 0x21 -#define TMP422_DEVICE_ID 0x22 -#define TMP423_DEVICE_ID 0x23 - -static const struct i2c_device_id tmp421_id[] = { - { "tmp421", 2 }, - { "tmp422", 3 }, - { "tmp423", 4 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, tmp421_id); - -struct tmp421_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; - unsigned long last_updated; - int channels; - u8 config; - s16 temp[4]; -}; - -static int temp_from_s16(s16 reg) -{ - /* Mask out status bits */ - int temp = reg & ~0xf; - - return (temp * 1000 + 128) / 256; -} - -static int temp_from_u16(u16 reg) -{ - /* Mask out status bits */ - int temp = reg & ~0xf; - - /* Add offset for extended temperature range. */ - temp -= 64 * 256; - - return (temp * 1000 + 128) / 256; -} - -static struct tmp421_data *tmp421_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct tmp421_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - data->config = i2c_smbus_read_byte_data(client, - TMP421_CONFIG_REG_1); - - for (i = 0; i < data->channels; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - TMP421_TEMP_MSB[i]) << 8; - data->temp[i] |= i2c_smbus_read_byte_data(client, - TMP421_TEMP_LSB[i]); - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static ssize_t show_temp_value(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp421_data *data = tmp421_update_device(dev); - int temp; - - mutex_lock(&data->update_lock); - if (data->config & TMP421_CONFIG_RANGE) - temp = temp_from_u16(data->temp[index]); - else - temp = temp_from_s16(data->temp[index]); - mutex_unlock(&data->update_lock); - - return sprintf(buf, "%d\n", temp); -} - -static ssize_t show_fault(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - int index = to_sensor_dev_attr(devattr)->index; - struct tmp421_data *data = tmp421_update_device(dev); - - /* - * The OPEN bit signals a fault. This is bit 0 of the temperature - * register (low byte). - */ - if (data->temp[index] & 0x01) - return sprintf(buf, "1\n"); - else - return sprintf(buf, "0\n"); -} - -static umode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a, - int n) -{ - struct device *dev = container_of(kobj, struct device, kobj); - struct tmp421_data *data = dev_get_drvdata(dev); - struct device_attribute *devattr; - unsigned int index; - - devattr = container_of(a, struct device_attribute, attr); - index = to_sensor_dev_attr(devattr)->index; - - if (index < data->channels) - return a->mode; - - return 0; -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0); -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1); -static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1); -static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2); -static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2); -static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3); -static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3); - -static struct attribute *tmp421_attr[] = { - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_fault.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_fault.dev_attr.attr, - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_fault.dev_attr.attr, - NULL -}; - -static const struct attribute_group tmp421_group = { - .attrs = tmp421_attr, - .is_visible = tmp421_is_visible, -}; - -static int tmp421_init_client(struct i2c_client *client) -{ - int config, config_orig; - - /* Set the conversion rate to 2 Hz */ - i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, 0x05); - - /* Start conversions (disable shutdown if necessary) */ - config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1); - if (config < 0) { - dev_err(&client->dev, "Could not read configuration" - " register (%d)\n", config); - return -ENODEV; - } - - config_orig = config; - config &= ~TMP421_CONFIG_SHUTDOWN; - - if (config != config_orig) { - dev_info(&client->dev, "Enable monitoring chip\n"); - i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, config); - } - - return 0; -} - -static int tmp421_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - enum chips kind; - struct i2c_adapter *adapter = client->adapter; - const char *names[] = { "TMP421", "TMP422", "TMP423" }; - u8 reg; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - reg = i2c_smbus_read_byte_data(client, TMP421_MANUFACTURER_ID_REG); - if (reg != TMP421_MANUFACTURER_ID) - return -ENODEV; - - reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG); - switch (reg) { - case TMP421_DEVICE_ID: - kind = tmp421; - break; - case TMP422_DEVICE_ID: - kind = tmp422; - break; - case TMP423_DEVICE_ID: - kind = tmp423; - break; - default: - return -ENODEV; - } - - strlcpy(info->type, tmp421_id[kind].name, I2C_NAME_SIZE); - dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n", - names[kind], client->addr); - - return 0; -} - -static int tmp421_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct tmp421_data *data; - int err; - - data = kzalloc(sizeof(struct tmp421_data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - data->channels = id->driver_data; - - err = tmp421_init_client(client); - if (err) - goto exit_free; - - err = sysfs_create_group(&client->dev.kobj, &tmp421_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - data->hwmon_dev = NULL; - goto exit_remove; - } - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &tmp421_group); - -exit_free: - kfree(data); - - return err; -} - -static int tmp421_remove(struct i2c_client *client) -{ - struct tmp421_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &tmp421_group); - - kfree(data); - - return 0; -} - -static struct i2c_driver tmp421_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "tmp421", - }, - .probe = tmp421_probe, - .remove = tmp421_remove, - .id_table = tmp421_id, - .detect = tmp421_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(tmp421_driver); - -MODULE_AUTHOR("Andre Prendel "); -MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor" - " driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/twl4030-madc-hwmon.c b/ANDROID_3.4.5/drivers/hwmon/twl4030-madc-hwmon.c deleted file mode 100644 index 0018c7dd..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/twl4030-madc-hwmon.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * TWL4030 MADC Hwmon driver-This driver monitors the real time - * conversion of analog signals like battery temperature, - * battery type, battery level etc. User can ask for the conversion on a - * particular channel using the sysfs nodes. - * - * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/ - * J Keerthy - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * sysfs hook function - */ -static ssize_t madc_read(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct twl4030_madc_request req; - long val; - - req.channels = (1 << attr->index); - req.method = TWL4030_MADC_SW2; - req.func_cb = NULL; - val = twl4030_madc_conversion(&req); - if (val < 0) - return val; - - return sprintf(buf, "%d\n", req.rbuf[attr->index]); -} - -/* sysfs nodes to read individual channels from user side */ -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8); -static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9); -static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10); -static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11); -static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12); -static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15); - -static struct attribute *twl4030_madc_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in9_input.dev_attr.attr, - &sensor_dev_attr_curr10_input.dev_attr.attr, - &sensor_dev_attr_in11_input.dev_attr.attr, - &sensor_dev_attr_in12_input.dev_attr.attr, - &sensor_dev_attr_in15_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group twl4030_madc_group = { - .attrs = twl4030_madc_attributes, -}; - -static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev) -{ - int ret; - struct device *hwmon; - - ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group); - if (ret) - goto err_sysfs; - hwmon = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon)) { - dev_err(&pdev->dev, "hwmon_device_register failed.\n"); - ret = PTR_ERR(hwmon); - goto err_reg; - } - - return 0; - -err_reg: - sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group); -err_sysfs: - - return ret; -} - -static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev) -{ - hwmon_device_unregister(&pdev->dev); - sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group); - - return 0; -} - -static struct platform_driver twl4030_madc_hwmon_driver = { - .probe = twl4030_madc_hwmon_probe, - .remove = __exit_p(twl4030_madc_hwmon_remove), - .driver = { - .name = "twl4030_madc_hwmon", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(twl4030_madc_hwmon_driver); - -MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("J Keerthy"); -MODULE_ALIAS("platform:twl4030_madc_hwmon"); diff --git a/ANDROID_3.4.5/drivers/hwmon/ultra45_env.c b/ANDROID_3.4.5/drivers/hwmon/ultra45_env.c deleted file mode 100644 index c315c59f..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/ultra45_env.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * ultra45_env.c: Driver for Ultra45 PIC16F747 environmental monitor. - * - * Copyright (C) 2008 David S. Miller - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_MODULE_VERSION "0.1" - -MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); -MODULE_DESCRIPTION("Ultra45 environmental monitor driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_MODULE_VERSION); - -/* PIC device registers */ -#define REG_CMD 0x00UL -#define REG_CMD_RESET 0x80 -#define REG_CMD_ESTAR 0x01 -#define REG_STAT 0x01UL -#define REG_STAT_FWVER 0xf0 -#define REG_STAT_TGOOD 0x08 -#define REG_STAT_STALE 0x04 -#define REG_STAT_BUSY 0x02 -#define REG_STAT_FAULT 0x01 -#define REG_DATA 0x40UL -#define REG_ADDR 0x41UL -#define REG_SIZE 0x42UL - -/* Registers accessed indirectly via REG_DATA/REG_ADDR */ -#define IREG_FAN0 0x00 -#define IREG_FAN1 0x01 -#define IREG_FAN2 0x02 -#define IREG_FAN3 0x03 -#define IREG_FAN4 0x04 -#define IREG_FAN5 0x05 -#define IREG_LCL_TEMP 0x06 -#define IREG_RMT1_TEMP 0x07 -#define IREG_RMT2_TEMP 0x08 -#define IREG_RMT3_TEMP 0x09 -#define IREG_LM95221_TEMP 0x0a -#define IREG_FIRE_TEMP 0x0b -#define IREG_LSI1064_TEMP 0x0c -#define IREG_FRONT_TEMP 0x0d -#define IREG_FAN_STAT 0x0e -#define IREG_VCORE0 0x0f -#define IREG_VCORE1 0x10 -#define IREG_VMEM0 0x11 -#define IREG_VMEM1 0x12 -#define IREG_PSU_TEMP 0x13 - -struct env { - void __iomem *regs; - spinlock_t lock; - - struct device *hwmon_dev; -}; - -static u8 env_read(struct env *p, u8 ireg) -{ - u8 ret; - - spin_lock(&p->lock); - writeb(ireg, p->regs + REG_ADDR); - ret = readb(p->regs + REG_DATA); - spin_unlock(&p->lock); - - return ret; -} - -static void env_write(struct env *p, u8 ireg, u8 val) -{ - spin_lock(&p->lock); - writeb(ireg, p->regs + REG_ADDR); - writeb(val, p->regs + REG_DATA); - spin_unlock(&p->lock); -} - -/* - * There seems to be a adr7462 providing these values, thus a lot - * of these calculations are borrowed from the adt7470 driver. - */ -#define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) -#define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM -#define FAN_PERIOD_INVALID (0xff << 8) -#define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) - -static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int fan_nr = to_sensor_dev_attr(attr)->index; - struct env *p = dev_get_drvdata(dev); - int rpm, period; - u8 val; - - val = env_read(p, IREG_FAN0 + fan_nr); - period = (int) val << 8; - if (FAN_DATA_VALID(period)) - rpm = FAN_PERIOD_TO_RPM(period); - else - rpm = 0; - - return sprintf(buf, "%d\n", rpm); -} - -static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int fan_nr = to_sensor_dev_attr(attr)->index; - unsigned long rpm; - struct env *p = dev_get_drvdata(dev); - int period; - u8 val; - int err; - - err = kstrtoul(buf, 10, &rpm); - if (err) - return err; - - if (!rpm) - return -EINVAL; - - period = FAN_RPM_TO_PERIOD(rpm); - val = period >> 8; - env_write(p, IREG_FAN0 + fan_nr, val); - - return count; -} - -static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int fan_nr = to_sensor_dev_attr(attr)->index; - struct env *p = dev_get_drvdata(dev); - u8 val = env_read(p, IREG_FAN_STAT); - return sprintf(buf, "%d\n", (val & (1 << fan_nr)) ? 1 : 0); -} - -#define fan(index) \ -static SENSOR_DEVICE_ATTR(fan##index##_speed, S_IRUGO | S_IWUSR, \ - show_fan_speed, set_fan_speed, index); \ -static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, \ - show_fan_fault, NULL, index) - -fan(0); -fan(1); -fan(2); -fan(3); -fan(4); - -static SENSOR_DEVICE_ATTR(psu_fan_fault, S_IRUGO, show_fan_fault, NULL, 6); - -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int temp_nr = to_sensor_dev_attr(attr)->index; - struct env *p = dev_get_drvdata(dev); - s8 val; - - val = env_read(p, IREG_LCL_TEMP + temp_nr); - return sprintf(buf, "%d\n", ((int) val) - 64); -} - -static SENSOR_DEVICE_ATTR(adt7462_local_temp, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(cpu0_temp, S_IRUGO, show_temp, NULL, 1); -static SENSOR_DEVICE_ATTR(cpu1_temp, S_IRUGO, show_temp, NULL, 2); -static SENSOR_DEVICE_ATTR(motherboard_temp, S_IRUGO, show_temp, NULL, 3); -static SENSOR_DEVICE_ATTR(lm95221_local_temp, S_IRUGO, show_temp, NULL, 4); -static SENSOR_DEVICE_ATTR(fire_temp, S_IRUGO, show_temp, NULL, 5); -static SENSOR_DEVICE_ATTR(lsi1064_local_temp, S_IRUGO, show_temp, NULL, 6); -static SENSOR_DEVICE_ATTR(front_panel_temp, S_IRUGO, show_temp, NULL, 7); -static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_temp, NULL, 13); - -static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int index = to_sensor_dev_attr(attr)->index; - struct env *p = dev_get_drvdata(dev); - u8 val; - - val = readb(p->regs + REG_STAT); - return sprintf(buf, "%d\n", (val & (1 << index)) ? 1 : 0); -} - -static SENSOR_DEVICE_ATTR(fan_failure, S_IRUGO, show_stat_bit, NULL, 0); -static SENSOR_DEVICE_ATTR(env_bus_busy, S_IRUGO, show_stat_bit, NULL, 1); -static SENSOR_DEVICE_ATTR(env_data_stale, S_IRUGO, show_stat_bit, NULL, 2); -static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL, - 3); - -static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct env *p = dev_get_drvdata(dev); - u8 val; - - val = readb(p->regs + REG_STAT); - return sprintf(buf, "%d\n", val >> 4); -} - -static SENSOR_DEVICE_ATTR(firmware_version, S_IRUGO, show_fwver, NULL, 0); - -static ssize_t show_name(struct device *dev, struct device_attribute *attr, - char *buf) -{ - return sprintf(buf, "ultra45\n"); -} - -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); - -static struct attribute *env_attributes[] = { - &sensor_dev_attr_fan0_speed.dev_attr.attr, - &sensor_dev_attr_fan0_fault.dev_attr.attr, - &sensor_dev_attr_fan1_speed.dev_attr.attr, - &sensor_dev_attr_fan1_fault.dev_attr.attr, - &sensor_dev_attr_fan2_speed.dev_attr.attr, - &sensor_dev_attr_fan2_fault.dev_attr.attr, - &sensor_dev_attr_fan3_speed.dev_attr.attr, - &sensor_dev_attr_fan3_fault.dev_attr.attr, - &sensor_dev_attr_fan4_speed.dev_attr.attr, - &sensor_dev_attr_fan4_fault.dev_attr.attr, - &sensor_dev_attr_psu_fan_fault.dev_attr.attr, - &sensor_dev_attr_adt7462_local_temp.dev_attr.attr, - &sensor_dev_attr_cpu0_temp.dev_attr.attr, - &sensor_dev_attr_cpu1_temp.dev_attr.attr, - &sensor_dev_attr_motherboard_temp.dev_attr.attr, - &sensor_dev_attr_lm95221_local_temp.dev_attr.attr, - &sensor_dev_attr_fire_temp.dev_attr.attr, - &sensor_dev_attr_lsi1064_local_temp.dev_attr.attr, - &sensor_dev_attr_front_panel_temp.dev_attr.attr, - &sensor_dev_attr_psu_temp.dev_attr.attr, - &sensor_dev_attr_fan_failure.dev_attr.attr, - &sensor_dev_attr_env_bus_busy.dev_attr.attr, - &sensor_dev_attr_env_data_stale.dev_attr.attr, - &sensor_dev_attr_tpm_self_test_passed.dev_attr.attr, - &sensor_dev_attr_firmware_version.dev_attr.attr, - &sensor_dev_attr_name.dev_attr.attr, - NULL, -}; - -static const struct attribute_group env_group = { - .attrs = env_attributes, -}; - -static int __devinit env_probe(struct platform_device *op) -{ - struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); - int err = -ENOMEM; - - if (!p) - goto out; - - spin_lock_init(&p->lock); - - p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747"); - if (!p->regs) - goto out_free; - - err = sysfs_create_group(&op->dev.kobj, &env_group); - if (err) - goto out_iounmap; - - p->hwmon_dev = hwmon_device_register(&op->dev); - if (IS_ERR(p->hwmon_dev)) { - err = PTR_ERR(p->hwmon_dev); - goto out_sysfs_remove_group; - } - - platform_set_drvdata(op, p); - err = 0; - -out: - return err; - -out_sysfs_remove_group: - sysfs_remove_group(&op->dev.kobj, &env_group); - -out_iounmap: - of_iounmap(&op->resource[0], p->regs, REG_SIZE); - -out_free: - kfree(p); - goto out; -} - -static int __devexit env_remove(struct platform_device *op) -{ - struct env *p = platform_get_drvdata(op); - - if (p) { - sysfs_remove_group(&op->dev.kobj, &env_group); - hwmon_device_unregister(p->hwmon_dev); - of_iounmap(&op->resource[0], p->regs, REG_SIZE); - kfree(p); - } - - return 0; -} - -static const struct of_device_id env_match[] = { - { - .name = "env-monitor", - .compatible = "SUNW,ebus-pic16f747-env", - }, - {}, -}; -MODULE_DEVICE_TABLE(of, env_match); - -static struct platform_driver env_driver = { - .driver = { - .name = "ultra45_env", - .owner = THIS_MODULE, - .of_match_table = env_match, - }, - .probe = env_probe, - .remove = __devexit_p(env_remove), -}; - -module_platform_driver(env_driver); diff --git a/ANDROID_3.4.5/drivers/hwmon/via-cputemp.c b/ANDROID_3.4.5/drivers/hwmon/via-cputemp.c deleted file mode 100644 index 8689664e..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/via-cputemp.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * via-cputemp.c - Driver for VIA CPU core temperature monitoring - * Copyright (C) 2009 VIA Technologies, Inc. - * - * based on existing coretemp.c, which is - * - * Copyright (C) 2007 Rudolf Marek - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRVNAME "via_cputemp" - -enum { SHOW_TEMP, SHOW_LABEL, SHOW_NAME }; - -/* - * Functions declaration - */ - -struct via_cputemp_data { - struct device *hwmon_dev; - const char *name; - u8 vrm; - u32 id; - u32 msr_temp; - u32 msr_vid; -}; - -/* - * Sysfs stuff - */ - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - int ret; - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct via_cputemp_data *data = dev_get_drvdata(dev); - - if (attr->index == SHOW_NAME) - ret = sprintf(buf, "%s\n", data->name); - else /* show label */ - ret = sprintf(buf, "Core %d\n", data->id); - return ret; -} - -static ssize_t show_temp(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct via_cputemp_data *data = dev_get_drvdata(dev); - u32 eax, edx; - int err; - - err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx); - if (err) - return -EAGAIN; - - return sprintf(buf, "%lu\n", ((unsigned long)eax & 0xffffff) * 1000); -} - -static ssize_t show_cpu_vid(struct device *dev, - struct device_attribute *devattr, char *buf) -{ - struct via_cputemp_data *data = dev_get_drvdata(dev); - u32 eax, edx; - int err; - - err = rdmsr_safe_on_cpu(data->id, data->msr_vid, &eax, &edx); - if (err) - return -EAGAIN; - - return sprintf(buf, "%d\n", vid_from_reg(~edx & 0x7f, data->vrm)); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, - SHOW_TEMP); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_name, NULL, SHOW_LABEL); -static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, SHOW_NAME); - -static struct attribute *via_cputemp_attributes[] = { - &sensor_dev_attr_name.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - NULL -}; - -static const struct attribute_group via_cputemp_group = { - .attrs = via_cputemp_attributes, -}; - -/* Optional attributes */ -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_cpu_vid, NULL); - -static int __devinit via_cputemp_probe(struct platform_device *pdev) -{ - struct via_cputemp_data *data; - struct cpuinfo_x86 *c = &cpu_data(pdev->id); - int err; - u32 eax, edx; - - data = kzalloc(sizeof(struct via_cputemp_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - dev_err(&pdev->dev, "Out of memory\n"); - goto exit; - } - - data->id = pdev->id; - data->name = "via_cputemp"; - - switch (c->x86_model) { - case 0xA: - /* C7 A */ - case 0xD: - /* C7 D */ - data->msr_temp = 0x1169; - data->msr_vid = 0x198; - break; - case 0xF: - /* Nano */ - data->msr_temp = 0x1423; - break; - default: - err = -ENODEV; - goto exit_free; - } - - /* test if we can access the TEMPERATURE MSR */ - err = rdmsr_safe_on_cpu(data->id, data->msr_temp, &eax, &edx); - if (err) { - dev_err(&pdev->dev, - "Unable to access TEMPERATURE MSR, giving up\n"); - goto exit_free; - } - - platform_set_drvdata(pdev, data); - - err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group); - if (err) - goto exit_free; - - if (data->msr_vid) - data->vrm = vid_which_vrm(); - - if (data->vrm) { - err = device_create_file(&pdev->dev, &dev_attr_cpu0_vid); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - dev_err(&pdev->dev, "Class registration failed (%d)\n", - err); - goto exit_remove; - } - - return 0; - -exit_remove: - if (data->vrm) - device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); - sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); -exit_free: - platform_set_drvdata(pdev, NULL); - kfree(data); -exit: - return err; -} - -static int __devexit via_cputemp_remove(struct platform_device *pdev) -{ - struct via_cputemp_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - if (data->vrm) - device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); - sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; -} - -static struct platform_driver via_cputemp_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = via_cputemp_probe, - .remove = __devexit_p(via_cputemp_remove), -}; - -struct pdev_entry { - struct list_head list; - struct platform_device *pdev; - unsigned int cpu; -}; - -static LIST_HEAD(pdev_list); -static DEFINE_MUTEX(pdev_list_mutex); - -static int __cpuinit via_cputemp_device_add(unsigned int cpu) -{ - int err; - struct platform_device *pdev; - struct pdev_entry *pdev_entry; - - pdev = platform_device_alloc(DRVNAME, cpu); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - pdev_entry = kzalloc(sizeof(struct pdev_entry), GFP_KERNEL); - if (!pdev_entry) { - err = -ENOMEM; - goto exit_device_put; - } - - err = platform_device_add(pdev); - if (err) { - pr_err("Device addition failed (%d)\n", err); - goto exit_device_free; - } - - pdev_entry->pdev = pdev; - pdev_entry->cpu = cpu; - mutex_lock(&pdev_list_mutex); - list_add_tail(&pdev_entry->list, &pdev_list); - mutex_unlock(&pdev_list_mutex); - - return 0; - -exit_device_free: - kfree(pdev_entry); -exit_device_put: - platform_device_put(pdev); -exit: - return err; -} - -static void __cpuinit via_cputemp_device_remove(unsigned int cpu) -{ - struct pdev_entry *p; - - mutex_lock(&pdev_list_mutex); - list_for_each_entry(p, &pdev_list, list) { - if (p->cpu == cpu) { - platform_device_unregister(p->pdev); - list_del(&p->list); - mutex_unlock(&pdev_list_mutex); - kfree(p); - return; - } - } - mutex_unlock(&pdev_list_mutex); -} - -static int __cpuinit via_cputemp_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - unsigned int cpu = (unsigned long) hcpu; - - switch (action) { - case CPU_ONLINE: - case CPU_DOWN_FAILED: - via_cputemp_device_add(cpu); - break; - case CPU_DOWN_PREPARE: - via_cputemp_device_remove(cpu); - break; - } - return NOTIFY_OK; -} - -static struct notifier_block via_cputemp_cpu_notifier __refdata = { - .notifier_call = via_cputemp_cpu_callback, -}; - -static const struct x86_cpu_id cputemp_ids[] = { - { X86_VENDOR_CENTAUR, 6, 0xa, }, /* C7 A */ - { X86_VENDOR_CENTAUR, 6, 0xd, }, /* C7 D */ - { X86_VENDOR_CENTAUR, 6, 0xf, }, /* Nano */ - {} -}; -MODULE_DEVICE_TABLE(x86cpu, cputemp_ids); - -static int __init via_cputemp_init(void) -{ - int i, err; - - if (!x86_match_cpu(cputemp_ids)) - return -ENODEV; - - err = platform_driver_register(&via_cputemp_driver); - if (err) - goto exit; - - for_each_online_cpu(i) { - struct cpuinfo_x86 *c = &cpu_data(i); - - if (c->x86 != 6) - continue; - - if (c->x86_model < 0x0a) - continue; - - if (c->x86_model > 0x0f) { - pr_warn("Unknown CPU model 0x%x\n", c->x86_model); - continue; - } - - via_cputemp_device_add(i); - } - -#ifndef CONFIG_HOTPLUG_CPU - if (list_empty(&pdev_list)) { - err = -ENODEV; - goto exit_driver_unreg; - } -#endif - - register_hotcpu_notifier(&via_cputemp_cpu_notifier); - return 0; - -#ifndef CONFIG_HOTPLUG_CPU -exit_driver_unreg: - platform_driver_unregister(&via_cputemp_driver); -#endif -exit: - return err; -} - -static void __exit via_cputemp_exit(void) -{ - struct pdev_entry *p, *n; - - unregister_hotcpu_notifier(&via_cputemp_cpu_notifier); - mutex_lock(&pdev_list_mutex); - list_for_each_entry_safe(p, n, &pdev_list, list) { - platform_device_unregister(p->pdev); - list_del(&p->list); - kfree(p); - } - mutex_unlock(&pdev_list_mutex); - platform_driver_unregister(&via_cputemp_driver); -} - -MODULE_AUTHOR("Harald Welte "); -MODULE_DESCRIPTION("VIA CPU temperature monitor"); -MODULE_LICENSE("GPL"); - -module_init(via_cputemp_init) -module_exit(via_cputemp_exit) diff --git a/ANDROID_3.4.5/drivers/hwmon/via686a.c b/ANDROID_3.4.5/drivers/hwmon/via686a.c deleted file mode 100644 index 288135d8..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/via686a.c +++ /dev/null @@ -1,976 +0,0 @@ -/* - * via686a.c - Part of lm_sensors, Linux kernel modules - * for hardware monitoring - * - * Copyright (c) 1998 - 2002 Frodo Looijaard , - * Kyösti Mälkki , - * Mark Studebaker , - * and Bob Dougherty - * - * (Some conversion-factor data were contributed by Jonathan Teh Soon Yew - * and Alex van Kaam .) - * - * 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 Via VT82C686A, VT82C686B south bridges. - * Reports all as a 686A. - * Warning - only supports a single device. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* - * If force_addr is set to anything different from 0, we forcibly enable - * the device at the given address. - */ -static unsigned short force_addr; -module_param(force_addr, ushort, 0); -MODULE_PARM_DESC(force_addr, - "Initialize the base address of the sensors"); - -static struct platform_device *pdev; - -/* - * The Via 686a southbridge has a LM78-like chip integrated on the same IC. - * This driver is a customized copy of lm78.c - */ - -/* Many VIA686A constants specified below */ - -/* Length of ISA address segment */ -#define VIA686A_EXTENT 0x80 -#define VIA686A_BASE_REG 0x70 -#define VIA686A_ENABLE_REG 0x74 - -/* The VIA686A registers */ -/* ins numbered 0-4 */ -#define VIA686A_REG_IN_MAX(nr) (0x2b + ((nr) * 2)) -#define VIA686A_REG_IN_MIN(nr) (0x2c + ((nr) * 2)) -#define VIA686A_REG_IN(nr) (0x22 + (nr)) - -/* fans numbered 1-2 */ -#define VIA686A_REG_FAN_MIN(nr) (0x3a + (nr)) -#define VIA686A_REG_FAN(nr) (0x28 + (nr)) - -/* temps numbered 1-3 */ -static const u8 VIA686A_REG_TEMP[] = { 0x20, 0x21, 0x1f }; -static const u8 VIA686A_REG_TEMP_OVER[] = { 0x39, 0x3d, 0x1d }; -static const u8 VIA686A_REG_TEMP_HYST[] = { 0x3a, 0x3e, 0x1e }; -/* bits 7-6 */ -#define VIA686A_REG_TEMP_LOW1 0x4b -/* 2 = bits 5-4, 3 = bits 7-6 */ -#define VIA686A_REG_TEMP_LOW23 0x49 - -#define VIA686A_REG_ALARM1 0x41 -#define VIA686A_REG_ALARM2 0x42 -#define VIA686A_REG_FANDIV 0x47 -#define VIA686A_REG_CONFIG 0x40 -/* - * The following register sets temp interrupt mode (bits 1-0 for temp1, - * 3-2 for temp2, 5-4 for temp3). Modes are: - * 00 interrupt stays as long as value is out-of-range - * 01 interrupt is cleared once register is read (default) - * 10 comparator mode- like 00, but ignores hysteresis - * 11 same as 00 - */ -#define VIA686A_REG_TEMP_MODE 0x4b -/* We'll just assume that you want to set all 3 simultaneously: */ -#define VIA686A_TEMP_MODE_MASK 0x3F -#define VIA686A_TEMP_MODE_CONTINUOUS 0x00 - -/* - * Conversions. Limit checking is only done on the TO_REG - * variants. - * - ******** VOLTAGE CONVERSIONS (Bob Dougherty) ******** - * From HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew): - * voltagefactor[0]=1.25/2628; (2628/1.25=2102.4) // Vccp - * voltagefactor[1]=1.25/2628; (2628/1.25=2102.4) // +2.5V - * voltagefactor[2]=1.67/2628; (2628/1.67=1573.7) // +3.3V - * voltagefactor[3]=2.6/2628; (2628/2.60=1010.8) // +5V - * voltagefactor[4]=6.3/2628; (2628/6.30=417.14) // +12V - * in[i]=(data[i+2]*25.0+133)*voltagefactor[i]; - * That is: - * volts = (25*regVal+133)*factor - * regVal = (volts/factor-133)/25 - * (These conversions were contributed by Jonathan Teh Soon Yew - * ) - */ -static inline u8 IN_TO_REG(long val, int inNum) -{ - /* - * To avoid floating point, we multiply constants by 10 (100 for +12V). - * Rounding is done (120500 is actually 133000 - 12500). - * Remember that val is expressed in 0.001V/bit, which is why we divide - * by an additional 10000 (100000 for +12V): 1000 for val and 10 (100) - * for the constants. - */ - if (inNum <= 1) - return (u8) - SENSORS_LIMIT((val * 21024 - 1205000) / 250000, 0, 255); - else if (inNum == 2) - return (u8) - SENSORS_LIMIT((val * 15737 - 1205000) / 250000, 0, 255); - else if (inNum == 3) - return (u8) - SENSORS_LIMIT((val * 10108 - 1205000) / 250000, 0, 255); - else - return (u8) - SENSORS_LIMIT((val * 41714 - 12050000) / 2500000, 0, 255); -} - -static inline long IN_FROM_REG(u8 val, int inNum) -{ - /* - * To avoid floating point, we multiply constants by 10 (100 for +12V). - * We also multiply them by 1000 because we want 0.001V/bit for the - * output value. Rounding is done. - */ - if (inNum <= 1) - return (long) ((250000 * val + 1330000 + 21024 / 2) / 21024); - else if (inNum == 2) - return (long) ((250000 * val + 1330000 + 15737 / 2) / 15737); - else if (inNum == 3) - return (long) ((250000 * val + 1330000 + 10108 / 2) / 10108); - else - return (long) ((2500000 * val + 13300000 + 41714 / 2) / 41714); -} - -/********* FAN RPM CONVERSIONS ********/ -/* - * Higher register values = slower fans (the fan's strobe gates a counter). - * But this chip saturates back at 0, not at 255 like all the other chips. - * So, 0 means 0 RPM - */ -static inline u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 0; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 255); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : (val) == 255 ? 0 : 1350000 / \ - ((val) * (div))) - -/******** TEMP CONVERSIONS (Bob Dougherty) *********/ -/* - * linear fits from HWMon.cpp (Copyright 1998-2000 Jonathan Teh Soon Yew) - * if(temp<169) - * return double(temp)*0.427-32.08; - * else if(temp>=169 && temp<=202) - * return double(temp)*0.582-58.16; - * else - * return double(temp)*0.924-127.33; - * - * A fifth-order polynomial fits the unofficial data (provided by Alex van - * Kaam ) a bit better. It also give more reasonable - * numbers on my machine (ie. they agree with what my BIOS tells me). - * Here's the fifth-order fit to the 8-bit data: - * temp = 1.625093e-10*val^5 - 1.001632e-07*val^4 + 2.457653e-05*val^3 - - * 2.967619e-03*val^2 + 2.175144e-01*val - 7.090067e+0. - * - * (2000-10-25- RFD: thanks to Uwe Andersen for - * finding my typos in this formula!) - * - * Alas, none of the elegant function-fit solutions will work because we - * aren't allowed to use floating point in the kernel and doing it with - * integers doesn't provide enough precision. So we'll do boring old - * look-up table stuff. The unofficial data (see below) have effectively - * 7-bit resolution (they are rounded to the nearest degree). I'm assuming - * that the transfer function of the device is monotonic and smooth, so a - * smooth function fit to the data will allow us to get better precision. - * I used the 5th-order poly fit described above and solved for - * VIA register values 0-255. I *10 before rounding, so we get tenth-degree - * precision. (I could have done all 1024 values for our 10-bit readings, - * but the function is very linear in the useful range (0-80 deg C), so - * we'll just use linear interpolation for 10-bit readings.) So, tempLUT - * is the temp at via register values 0-255: - */ -static const s16 tempLUT[] = { - -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519, - -503, -487, -471, -456, -442, -428, -414, -400, -387, -375, - -362, -350, -339, -327, -316, -305, -295, -285, -275, -265, - -255, -246, -237, -229, -220, -212, -204, -196, -188, -180, - -173, -166, -159, -152, -145, -139, -132, -126, -120, -114, - -108, -102, -96, -91, -85, -80, -74, -69, -64, -59, -54, -49, - -44, -39, -34, -29, -25, -20, -15, -11, -6, -2, 3, 7, 12, 16, - 20, 25, 29, 33, 37, 42, 46, 50, 54, 59, 63, 67, 71, 75, 79, 84, - 88, 92, 96, 100, 104, 109, 113, 117, 121, 125, 130, 134, 138, - 142, 146, 151, 155, 159, 163, 168, 172, 176, 181, 185, 189, - 193, 198, 202, 206, 211, 215, 219, 224, 228, 232, 237, 241, - 245, 250, 254, 259, 263, 267, 272, 276, 281, 285, 290, 294, - 299, 303, 307, 312, 316, 321, 325, 330, 334, 339, 344, 348, - 353, 357, 362, 366, 371, 376, 380, 385, 390, 395, 399, 404, - 409, 414, 419, 423, 428, 433, 438, 443, 449, 454, 459, 464, - 469, 475, 480, 486, 491, 497, 502, 508, 514, 520, 526, 532, - 538, 544, 551, 557, 564, 571, 578, 584, 592, 599, 606, 614, - 621, 629, 637, 645, 654, 662, 671, 680, 689, 698, 708, 718, - 728, 738, 749, 759, 770, 782, 793, 805, 818, 830, 843, 856, - 870, 883, 898, 912, 927, 943, 958, 975, 991, 1008, 1026, 1044, - 1062, 1081, 1101, 1121, 1141, 1162, 1184, 1206, 1229, 1252, - 1276, 1301, 1326, 1352, 1378, 1406, 1434, 1462 -}; - -/* - * the original LUT values from Alex van Kaam - * (for via register values 12-240): - * {-50,-49,-47,-45,-43,-41,-39,-38,-37,-35,-34,-33,-32,-31, - * -30,-29,-28,-27,-26,-25,-24,-24,-23,-22,-21,-20,-20,-19,-18,-17,-17,-16,-15, - * -15,-14,-14,-13,-12,-12,-11,-11,-10,-9,-9,-8,-8,-7,-7,-6,-6,-5,-5,-4,-4,-3, - * -3,-2,-2,-1,-1,0,0,1,1,1,3,3,3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,9,10,10,11,11,12, - * 12,12,13,13,13,14,14,15,15,16,16,16,17,17,18,18,19,19,20,20,21,21,21,22,22, - * 22,23,23,24,24,25,25,26,26,26,27,27,27,28,28,29,29,30,30,30,31,31,32,32,33, - * 33,34,34,35,35,35,36,36,37,37,38,38,39,39,40,40,41,41,42,42,43,43,44,44,45, - * 45,46,46,47,48,48,49,49,50,51,51,52,52,53,53,54,55,55,56,57,57,58,59,59,60, - * 61,62,62,63,64,65,66,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,83,84, - * 85,86,88,89,91,92,94,96,97,99,101,103,105,107,109,110}; - * - * - * Here's the reverse LUT. I got it by doing a 6-th order poly fit (needed - * an extra term for a good fit to these inverse data!) and then - * solving for each temp value from -50 to 110 (the useable range for - * this chip). Here's the fit: - * viaRegVal = -1.160370e-10*val^6 +3.193693e-08*val^5 - 1.464447e-06*val^4 - * - 2.525453e-04*val^3 + 1.424593e-02*val^2 + 2.148941e+00*val +7.275808e+01) - * Note that n=161: - */ -static const u8 viaLUT[] = { - 12, 12, 13, 14, 14, 15, 16, 16, 17, 18, 18, 19, 20, 20, 21, 22, 23, - 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 35, 36, 37, 39, 40, - 41, 43, 45, 46, 48, 49, 51, 53, 55, 57, 59, 60, 62, 64, 66, - 69, 71, 73, 75, 77, 79, 82, 84, 86, 88, 91, 93, 95, 98, 100, - 103, 105, 107, 110, 112, 115, 117, 119, 122, 124, 126, 129, - 131, 134, 136, 138, 140, 143, 145, 147, 150, 152, 154, 156, - 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, - 182, 183, 185, 187, 188, 190, 192, 193, 195, 196, 198, 199, - 200, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213, - 214, 215, 216, 217, 218, 219, 220, 221, 222, 222, 223, 224, - 225, 226, 226, 227, 228, 228, 229, 230, 230, 231, 232, 232, - 233, 233, 234, 235, 235, 236, 236, 237, 237, 238, 238, 239, - 239, 240 -}; - -/* - * Converting temps to (8-bit) hyst and over registers - * No interpolation here. - * The +50 is because the temps start at -50 - */ -static inline u8 TEMP_TO_REG(long val) -{ - return viaLUT[val <= -50000 ? 0 : val >= 110000 ? 160 : - (val < 0 ? val - 500 : val + 500) / 1000 + 50]; -} - -/* for 8-bit temperature hyst and over registers */ -#define TEMP_FROM_REG(val) ((long)tempLUT[val] * 100) - -/* for 10-bit temperature readings */ -static inline long TEMP_FROM_REG10(u16 val) -{ - u16 eightBits = val >> 2; - u16 twoBits = val & 3; - - /* no interpolation for these */ - if (twoBits == 0 || eightBits == 255) - return TEMP_FROM_REG(eightBits); - - /* do some linear interpolation */ - return (tempLUT[eightBits] * (4 - twoBits) + - tempLUT[eightBits + 1] * twoBits) * 25; -} - -#define DIV_FROM_REG(val) (1 << (val)) -#define DIV_TO_REG(val) ((val) == 8 ? 3 : (val) == 4 ? 2 : (val) == 1 ? 0 : 1) - -/* - * For each registered chip, we need to keep some data in memory. - * The structure is dynamically allocated. - */ -struct via686a_data { - unsigned short addr; - const char *name; - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[5]; /* Register value */ - u8 in_max[5]; /* Register value */ - u8 in_min[5]; /* Register value */ - u8 fan[2]; /* Register value */ - u8 fan_min[2]; /* Register value */ - u16 temp[3]; /* Register value 10 bit */ - u8 temp_over[3]; /* Register value */ - u8 temp_hyst[3]; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ - u16 alarms; /* Register encoding, combined */ -}; - -static struct pci_dev *s_bridge; /* pointer to the (only) via686a */ - -static int via686a_probe(struct platform_device *pdev); -static int __devexit via686a_remove(struct platform_device *pdev); - -static inline int via686a_read_value(struct via686a_data *data, u8 reg) -{ - return inb_p(data->addr + reg); -} - -static inline void via686a_write_value(struct via686a_data *data, u8 reg, - u8 value) -{ - outb_p(value, data->addr + reg); -} - -static struct via686a_data *via686a_update_device(struct device *dev); -static void via686a_init_device(struct via686a_data *data); - -/* following are the sysfs callback functions */ - -/* 7 voltage sensors */ -static ssize_t show_in(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr)); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr)); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr)); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) { - struct via686a_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val, nr); - via686a_write_value(data, VIA686A_REG_IN_MIN(nr), - data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_in_max(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) { - struct via686a_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val, nr); - via686a_write_value(data, VIA686A_REG_IN_MAX(nr), - data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} -#define show_in_offset(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset); - -show_in_offset(0); -show_in_offset(1); -show_in_offset(2); -show_in_offset(3); -show_in_offset(4); - -/* 3 temperatures */ -static ssize_t show_temp(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr])); -} -static ssize_t show_temp_over(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr])); -} -static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr])); -} -static ssize_t set_temp_over(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) { - struct via686a_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_over[nr] = TEMP_TO_REG(val); - via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr], - data->temp_over[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) { - struct via686a_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_hyst[nr] = TEMP_TO_REG(val); - via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr], - data->temp_hyst[nr]); - mutex_unlock(&data->update_lock); - return count; -} -#define show_temp_offset(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_over, set_temp_over, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_hyst, set_temp_hyst, offset - 1); - -show_temp_offset(1); -show_temp_offset(2); -show_temp_offset(3); - -/* 2 Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t show_fan_min(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", - FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t show_fan_div(struct device *dev, struct device_attribute *da, - char *buf) { - struct via686a_data *data = via686a_update_device(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} -static ssize_t set_fan_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) { - struct via686a_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) { - struct via686a_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - int nr = attr->index; - int old; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - old = via686a_read_value(data, VIA686A_REG_FANDIV); - data->fan_div[nr] = DIV_TO_REG(val); - old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - via686a_write_value(data, VIA686A_REG_FANDIV, old); - mutex_unlock(&data->update_lock); - return count; -} - -#define show_fan_offset(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1); - -show_fan_offset(1); -show_fan_offset(2); - -/* Alarms */ -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct via686a_data *data = via686a_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 15); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct via686a_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *via686a_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - - &dev_attr_alarms.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group via686a_group = { - .attrs = via686a_attributes, -}; - -static struct platform_driver via686a_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "via686a", - }, - .probe = via686a_probe, - .remove = __devexit_p(via686a_remove), -}; - - -/* This is called when the module is loaded */ -static int __devinit via686a_probe(struct platform_device *pdev) -{ - struct via686a_data *data; - struct resource *res; - int err; - - /* Reserve the ISA region */ - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, VIA686A_EXTENT, - via686a_driver.driver.name)) { - dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n", - (unsigned long)res->start, (unsigned long)res->end); - return -ENODEV; - } - - data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release; - } - - platform_set_drvdata(pdev, data); - data->addr = res->start; - data->name = "via686a"; - mutex_init(&data->update_lock); - - /* Initialize the VIA686A chip */ - via686a_init_device(data); - - /* Register sysfs hooks */ - err = sysfs_create_group(&pdev->dev.kobj, &via686a_group); - if (err) - goto exit_free; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&pdev->dev.kobj, &via686a_group); -exit_free: - kfree(data); -exit_release: - release_region(res->start, VIA686A_EXTENT); - return err; -} - -static int __devexit via686a_remove(struct platform_device *pdev) -{ - struct via686a_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &via686a_group); - - release_region(data->addr, VIA686A_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); - - return 0; -} - -static void via686a_update_fan_div(struct via686a_data *data) -{ - int reg = via686a_read_value(data, VIA686A_REG_FANDIV); - data->fan_div[0] = (reg >> 4) & 0x03; - data->fan_div[1] = reg >> 6; -} - -static void __devinit via686a_init_device(struct via686a_data *data) -{ - u8 reg; - - /* Start monitoring */ - reg = via686a_read_value(data, VIA686A_REG_CONFIG); - via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F); - - /* Configure temp interrupt mode for continuous-interrupt operation */ - reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE); - via686a_write_value(data, VIA686A_REG_TEMP_MODE, - (reg & ~VIA686A_TEMP_MODE_MASK) - | VIA686A_TEMP_MODE_CONTINUOUS); - - /* Pre-read fan clock divisor values */ - via686a_update_fan_div(data); -} - -static struct via686a_data *via686a_update_device(struct device *dev) -{ - struct via686a_data *data = dev_get_drvdata(dev); - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - for (i = 0; i <= 4; i++) { - data->in[i] = - via686a_read_value(data, VIA686A_REG_IN(i)); - data->in_min[i] = via686a_read_value(data, - VIA686A_REG_IN_MIN - (i)); - data->in_max[i] = - via686a_read_value(data, VIA686A_REG_IN_MAX(i)); - } - for (i = 1; i <= 2; i++) { - data->fan[i - 1] = - via686a_read_value(data, VIA686A_REG_FAN(i)); - data->fan_min[i - 1] = via686a_read_value(data, - VIA686A_REG_FAN_MIN(i)); - } - for (i = 0; i <= 2; i++) { - data->temp[i] = via686a_read_value(data, - VIA686A_REG_TEMP[i]) << 2; - data->temp_over[i] = - via686a_read_value(data, - VIA686A_REG_TEMP_OVER[i]); - data->temp_hyst[i] = - via686a_read_value(data, - VIA686A_REG_TEMP_HYST[i]); - } - /* - * add in lower 2 bits - * temp1 uses bits 7-6 of VIA686A_REG_TEMP_LOW1 - * temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23 - * temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23 - */ - data->temp[0] |= (via686a_read_value(data, - VIA686A_REG_TEMP_LOW1) - & 0xc0) >> 6; - data->temp[1] |= - (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & - 0x30) >> 4; - data->temp[2] |= - (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) & - 0xc0) >> 6; - - via686a_update_fan_div(data); - data->alarms = - via686a_read_value(data, - VIA686A_REG_ALARM1) | - (via686a_read_value(data, VIA686A_REG_ALARM2) << 8); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static DEFINE_PCI_DEVICE_TABLE(via686a_pci_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4) }, - { } -}; -MODULE_DEVICE_TABLE(pci, via686a_pci_ids); - -static int __devinit via686a_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + VIA686A_EXTENT - 1, - .name = "via686a", - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc("via686a", address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - return err; -} - -static int __devinit via686a_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - u16 address, val; - - if (force_addr) { - address = force_addr & ~(VIA686A_EXTENT - 1); - dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VIA686A_BASE_REG, address | 1)) - return -ENODEV; - } - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, VIA686A_BASE_REG, &val)) - return -ENODEV; - - address = val & ~(VIA686A_EXTENT - 1); - if (address == 0) { - dev_err(&dev->dev, "base address not set - upgrade BIOS " - "or use force_addr=0xaddr\n"); - return -ENODEV; - } - - if (PCIBIOS_SUCCESSFUL != - pci_read_config_word(dev, VIA686A_ENABLE_REG, &val)) - return -ENODEV; - if (!(val & 0x0001)) { - if (!force_addr) { - dev_warn(&dev->dev, "Sensors disabled, enable " - "with force_addr=0x%x\n", address); - return -ENODEV; - } - - dev_warn(&dev->dev, "Enabling sensors\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VIA686A_ENABLE_REG, - val | 0x0001)) - return -ENODEV; - } - - if (platform_driver_register(&via686a_driver)) - goto exit; - - /* Sets global pdev as a side effect */ - if (via686a_device_add(address)) - goto exit_unregister; - - /* - * Always return failure here. This is to allow other drivers to bind - * to this pci device. We don't really want to have control over the - * pci device, we only wanted to read as few register values from it. - */ - s_bridge = pci_dev_get(dev); - return -ENODEV; - -exit_unregister: - platform_driver_unregister(&via686a_driver); -exit: - return -ENODEV; -} - -static struct pci_driver via686a_pci_driver = { - .name = "via686a", - .id_table = via686a_pci_ids, - .probe = via686a_pci_probe, -}; - -static int __init sm_via686a_init(void) -{ - return pci_register_driver(&via686a_pci_driver); -} - -static void __exit sm_via686a_exit(void) -{ - pci_unregister_driver(&via686a_pci_driver); - if (s_bridge != NULL) { - platform_device_unregister(pdev); - platform_driver_unregister(&via686a_driver); - pci_dev_put(s_bridge); - s_bridge = NULL; - } -} - -MODULE_AUTHOR("Kyösti Mälkki , " - "Mark Studebaker " - "and Bob Dougherty "); -MODULE_DESCRIPTION("VIA 686A Sensor device"); -MODULE_LICENSE("GPL"); - -module_init(sm_via686a_init); -module_exit(sm_via686a_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/vt1211.c b/ANDROID_3.4.5/drivers/hwmon/vt1211.c deleted file mode 100644 index c2c5c72f..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/vt1211.c +++ /dev/null @@ -1,1380 +0,0 @@ -/* - * vt1211.c - driver for the VIA VT1211 Super-I/O chip integrated hardware - * monitoring features - * Copyright (C) 2006 Juerg Haefliger - * - * This driver is based on the driver for kernel 2.4 by Mark D. Studebaker - * and its port to kernel 2.6 by Lars Ekman. - * - * 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. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int uch_config = -1; -module_param(uch_config, int, 0); -MODULE_PARM_DESC(uch_config, "Initialize the universal channel configuration"); - -static int int_mode = -1; -module_param(int_mode, int, 0); -MODULE_PARM_DESC(int_mode, "Force the temperature interrupt mode"); - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -static struct platform_device *pdev; - -#define DRVNAME "vt1211" - -/* --------------------------------------------------------------------- - * Registers - * - * The sensors are defined as follows. - * - * Sensor Voltage Mode Temp Mode Notes (from the datasheet) - * -------- ------------ --------- -------------------------- - * Reading 1 temp1 Intel thermal diode - * Reading 3 temp2 Internal thermal diode - * UCH1/Reading2 in0 temp3 NTC type thermistor - * UCH2 in1 temp4 +2.5V - * UCH3 in2 temp5 VccP - * UCH4 in3 temp6 +5V - * UCH5 in4 temp7 +12V - * 3.3V in5 Internal VDD (+3.3V) - * - * --------------------------------------------------------------------- */ - -/* Voltages (in) numbered 0-5 (ix) */ -#define VT1211_REG_IN(ix) (0x21 + (ix)) -#define VT1211_REG_IN_MIN(ix) ((ix) == 0 ? 0x3e : 0x2a + 2 * (ix)) -#define VT1211_REG_IN_MAX(ix) ((ix) == 0 ? 0x3d : 0x29 + 2 * (ix)) - -/* Temperatures (temp) numbered 0-6 (ix) */ -static u8 regtemp[] = {0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25}; -static u8 regtempmax[] = {0x39, 0x1d, 0x3d, 0x2b, 0x2d, 0x2f, 0x31}; -static u8 regtemphyst[] = {0x3a, 0x1e, 0x3e, 0x2c, 0x2e, 0x30, 0x32}; - -/* Fans numbered 0-1 (ix) */ -#define VT1211_REG_FAN(ix) (0x29 + (ix)) -#define VT1211_REG_FAN_MIN(ix) (0x3b + (ix)) -#define VT1211_REG_FAN_DIV 0x47 - -/* PWMs numbered 0-1 (ix) */ -/* Auto points numbered 0-3 (ap) */ -#define VT1211_REG_PWM(ix) (0x60 + (ix)) -#define VT1211_REG_PWM_CLK 0x50 -#define VT1211_REG_PWM_CTL 0x51 -#define VT1211_REG_PWM_AUTO_TEMP(ap) (0x55 - (ap)) -#define VT1211_REG_PWM_AUTO_PWM(ix, ap) (0x58 + 2 * (ix) - (ap)) - -/* Miscellaneous registers */ -#define VT1211_REG_CONFIG 0x40 -#define VT1211_REG_ALARM1 0x41 -#define VT1211_REG_ALARM2 0x42 -#define VT1211_REG_VID 0x45 -#define VT1211_REG_UCH_CONFIG 0x4a -#define VT1211_REG_TEMP1_CONFIG 0x4b -#define VT1211_REG_TEMP2_CONFIG 0x4c - -/* In, temp & fan alarm bits */ -static const u8 bitalarmin[] = {11, 0, 1, 3, 8, 2, 9}; -static const u8 bitalarmtemp[] = {4, 15, 11, 0, 1, 3, 8}; -static const u8 bitalarmfan[] = {6, 7}; - -/* --------------------------------------------------------------------- - * Data structures and manipulation thereof - * --------------------------------------------------------------------- */ - -struct vt1211_data { - unsigned short addr; - const char *name; - struct device *hwmon_dev; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* Register values */ - u8 in[6]; - u8 in_max[6]; - u8 in_min[6]; - u8 temp[7]; - u8 temp_max[7]; - u8 temp_hyst[7]; - u8 fan[2]; - u8 fan_min[2]; - u8 fan_div[2]; - u8 fan_ctl; - u8 pwm[2]; - u8 pwm_ctl[2]; - u8 pwm_clk; - u8 pwm_auto_temp[4]; - u8 pwm_auto_pwm[2][4]; - u8 vid; /* Read once at init time */ - u8 vrm; - u8 uch_config; /* Read once at init time */ - u16 alarms; -}; - -/* ix = [0-5] */ -#define ISVOLT(ix, uch_config) ((ix) > 4 ? 1 : \ - !(((uch_config) >> ((ix) + 2)) & 1)) - -/* ix = [0-6] */ -#define ISTEMP(ix, uch_config) ((ix) < 2 ? 1 : \ - ((uch_config) >> (ix)) & 1) - -/* - * in5 (ix = 5) is special. It's the internal 3.3V so it's scaled in the - * driver according to the VT1211 BIOS porting guide - */ -#define IN_FROM_REG(ix, reg) ((reg) < 3 ? 0 : (ix) == 5 ? \ - (((reg) - 3) * 15882 + 479) / 958 : \ - (((reg) - 3) * 10000 + 479) / 958) -#define IN_TO_REG(ix, val) (SENSORS_LIMIT((ix) == 5 ? \ - ((val) * 958 + 7941) / 15882 + 3 : \ - ((val) * 958 + 5000) / 10000 + 3, 0, 255)) - -/* - * temp1 (ix = 0) is an intel thermal diode which is scaled in user space. - * temp2 (ix = 1) is the internal temp diode so it's scaled in the driver - * according to some measurements that I took on an EPIA M10000. - * temp3-7 are thermistor based so the driver returns the voltage measured at - * the pin (range 0V - 2.2V). - */ -#define TEMP_FROM_REG(ix, reg) ((ix) == 0 ? (reg) * 1000 : \ - (ix) == 1 ? (reg) < 51 ? 0 : \ - ((reg) - 51) * 1000 : \ - ((253 - (reg)) * 2200 + 105) / 210) -#define TEMP_TO_REG(ix, val) SENSORS_LIMIT( \ - ((ix) == 0 ? ((val) + 500) / 1000 : \ - (ix) == 1 ? ((val) + 500) / 1000 + 51 : \ - 253 - ((val) * 210 + 1100) / 2200), 0, 255) - -#define DIV_FROM_REG(reg) (1 << (reg)) - -#define RPM_FROM_REG(reg, div) (((reg) == 0) || ((reg) == 255) ? 0 : \ - 1310720 / (reg) / DIV_FROM_REG(div)) -#define RPM_TO_REG(val, div) ((val) == 0 ? 255 : \ - SENSORS_LIMIT((1310720 / (val) / \ - DIV_FROM_REG(div)), 1, 254)) - -/* --------------------------------------------------------------------- - * Super-I/O constants and functions - * --------------------------------------------------------------------- */ - -/* - * Configuration index port registers - * The vt1211 can live at 2 different addresses so we need to probe both - */ -#define SIO_REG_CIP1 0x2e -#define SIO_REG_CIP2 0x4e - -/* Configuration registers */ -#define SIO_VT1211_LDN 0x07 /* logical device number */ -#define SIO_VT1211_DEVID 0x20 /* device ID */ -#define SIO_VT1211_DEVREV 0x21 /* device revision */ -#define SIO_VT1211_ACTIVE 0x30 /* HW monitor active */ -#define SIO_VT1211_BADDR 0x60 /* base I/O address */ -#define SIO_VT1211_ID 0x3c /* VT1211 device ID */ - -/* VT1211 logical device numbers */ -#define SIO_VT1211_LDN_HWMON 0x0b /* HW monitor */ - -static inline void superio_outb(int sio_cip, int reg, int val) -{ - outb(reg, sio_cip); - outb(val, sio_cip + 1); -} - -static inline int superio_inb(int sio_cip, int reg) -{ - outb(reg, sio_cip); - return inb(sio_cip + 1); -} - -static inline void superio_select(int sio_cip, int ldn) -{ - outb(SIO_VT1211_LDN, sio_cip); - outb(ldn, sio_cip + 1); -} - -static inline void superio_enter(int sio_cip) -{ - outb(0x87, sio_cip); - outb(0x87, sio_cip); -} - -static inline void superio_exit(int sio_cip) -{ - outb(0xaa, sio_cip); -} - -/* --------------------------------------------------------------------- - * Device I/O access - * --------------------------------------------------------------------- */ - -static inline u8 vt1211_read8(struct vt1211_data *data, u8 reg) -{ - return inb(data->addr + reg); -} - -static inline void vt1211_write8(struct vt1211_data *data, u8 reg, u8 val) -{ - outb(val, data->addr + reg); -} - -static struct vt1211_data *vt1211_update_device(struct device *dev) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - int ix, val; - - mutex_lock(&data->update_lock); - - /* registers cache is refreshed after 1 second */ - if (time_after(jiffies, data->last_updated + HZ) || !data->valid) { - /* read VID */ - data->vid = vt1211_read8(data, VT1211_REG_VID) & 0x1f; - - /* voltage (in) registers */ - for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) { - if (ISVOLT(ix, data->uch_config)) { - data->in[ix] = vt1211_read8(data, - VT1211_REG_IN(ix)); - data->in_min[ix] = vt1211_read8(data, - VT1211_REG_IN_MIN(ix)); - data->in_max[ix] = vt1211_read8(data, - VT1211_REG_IN_MAX(ix)); - } - } - - /* temp registers */ - for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) { - if (ISTEMP(ix, data->uch_config)) { - data->temp[ix] = vt1211_read8(data, - regtemp[ix]); - data->temp_max[ix] = vt1211_read8(data, - regtempmax[ix]); - data->temp_hyst[ix] = vt1211_read8(data, - regtemphyst[ix]); - } - } - - /* fan & pwm registers */ - for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) { - data->fan[ix] = vt1211_read8(data, - VT1211_REG_FAN(ix)); - data->fan_min[ix] = vt1211_read8(data, - VT1211_REG_FAN_MIN(ix)); - data->pwm[ix] = vt1211_read8(data, - VT1211_REG_PWM(ix)); - } - val = vt1211_read8(data, VT1211_REG_FAN_DIV); - data->fan_div[0] = (val >> 4) & 3; - data->fan_div[1] = (val >> 6) & 3; - data->fan_ctl = val & 0xf; - - val = vt1211_read8(data, VT1211_REG_PWM_CTL); - data->pwm_ctl[0] = val & 0xf; - data->pwm_ctl[1] = (val >> 4) & 0xf; - - data->pwm_clk = vt1211_read8(data, VT1211_REG_PWM_CLK); - - /* pwm & temp auto point registers */ - data->pwm_auto_pwm[0][1] = vt1211_read8(data, - VT1211_REG_PWM_AUTO_PWM(0, 1)); - data->pwm_auto_pwm[0][2] = vt1211_read8(data, - VT1211_REG_PWM_AUTO_PWM(0, 2)); - data->pwm_auto_pwm[1][1] = vt1211_read8(data, - VT1211_REG_PWM_AUTO_PWM(1, 1)); - data->pwm_auto_pwm[1][2] = vt1211_read8(data, - VT1211_REG_PWM_AUTO_PWM(1, 2)); - for (ix = 0; ix < ARRAY_SIZE(data->pwm_auto_temp); ix++) { - data->pwm_auto_temp[ix] = vt1211_read8(data, - VT1211_REG_PWM_AUTO_TEMP(ix)); - } - - /* alarm registers */ - data->alarms = (vt1211_read8(data, VT1211_REG_ALARM2) << 8) | - vt1211_read8(data, VT1211_REG_ALARM1); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -/* --------------------------------------------------------------------- - * Voltage sysfs interfaces - * ix = [0-5] - * --------------------------------------------------------------------- */ - -#define SHOW_IN_INPUT 0 -#define SHOW_SET_IN_MIN 1 -#define SHOW_SET_IN_MAX 2 -#define SHOW_IN_ALARM 3 - -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SHOW_IN_INPUT: - res = IN_FROM_REG(ix, data->in[ix]); - break; - case SHOW_SET_IN_MIN: - res = IN_FROM_REG(ix, data->in_min[ix]); - break; - case SHOW_SET_IN_MAX: - res = IN_FROM_REG(ix, data->in_max[ix]); - break; - case SHOW_IN_ALARM: - res = (data->alarms >> bitalarmin[ix]) & 1; - break; - default: - res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_in(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SHOW_SET_IN_MIN: - data->in_min[ix] = IN_TO_REG(ix, val); - vt1211_write8(data, VT1211_REG_IN_MIN(ix), data->in_min[ix]); - break; - case SHOW_SET_IN_MAX: - data->in_max[ix] = IN_TO_REG(ix, val); - vt1211_write8(data, VT1211_REG_IN_MAX(ix), data->in_max[ix]); - break; - default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Temperature sysfs interfaces - * ix = [0-6] - * --------------------------------------------------------------------- */ - -#define SHOW_TEMP_INPUT 0 -#define SHOW_SET_TEMP_MAX 1 -#define SHOW_SET_TEMP_MAX_HYST 2 -#define SHOW_TEMP_ALARM 3 - -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SHOW_TEMP_INPUT: - res = TEMP_FROM_REG(ix, data->temp[ix]); - break; - case SHOW_SET_TEMP_MAX: - res = TEMP_FROM_REG(ix, data->temp_max[ix]); - break; - case SHOW_SET_TEMP_MAX_HYST: - res = TEMP_FROM_REG(ix, data->temp_hyst[ix]); - break; - case SHOW_TEMP_ALARM: - res = (data->alarms >> bitalarmtemp[ix]) & 1; - break; - default: - res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (fn) { - case SHOW_SET_TEMP_MAX: - data->temp_max[ix] = TEMP_TO_REG(ix, val); - vt1211_write8(data, regtempmax[ix], - data->temp_max[ix]); - break; - case SHOW_SET_TEMP_MAX_HYST: - data->temp_hyst[ix] = TEMP_TO_REG(ix, val); - vt1211_write8(data, regtemphyst[ix], - data->temp_hyst[ix]); - break; - default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Fan sysfs interfaces - * ix = [0-1] - * --------------------------------------------------------------------- */ - -#define SHOW_FAN_INPUT 0 -#define SHOW_SET_FAN_MIN 1 -#define SHOW_SET_FAN_DIV 2 -#define SHOW_FAN_ALARM 3 - -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SHOW_FAN_INPUT: - res = RPM_FROM_REG(data->fan[ix], data->fan_div[ix]); - break; - case SHOW_SET_FAN_MIN: - res = RPM_FROM_REG(data->fan_min[ix], data->fan_div[ix]); - break; - case SHOW_SET_FAN_DIV: - res = DIV_FROM_REG(data->fan_div[ix]); - break; - case SHOW_FAN_ALARM: - res = (data->alarms >> bitalarmfan[ix]) & 1; - break; - default: - res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_fan(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - /* sync the data cache */ - reg = vt1211_read8(data, VT1211_REG_FAN_DIV); - data->fan_div[0] = (reg >> 4) & 3; - data->fan_div[1] = (reg >> 6) & 3; - data->fan_ctl = reg & 0xf; - - switch (fn) { - case SHOW_SET_FAN_MIN: - data->fan_min[ix] = RPM_TO_REG(val, data->fan_div[ix]); - vt1211_write8(data, VT1211_REG_FAN_MIN(ix), - data->fan_min[ix]); - break; - case SHOW_SET_FAN_DIV: - switch (val) { - case 1: - data->fan_div[ix] = 0; - break; - case 2: - data->fan_div[ix] = 1; - break; - case 4: - data->fan_div[ix] = 2; - break; - case 8: - data->fan_div[ix] = 3; - break; - default: - count = -EINVAL; - dev_warn(dev, "fan div value %ld not supported. " - "Choose one of 1, 2, 4, or 8.\n", val); - goto EXIT; - } - vt1211_write8(data, VT1211_REG_FAN_DIV, - ((data->fan_div[1] << 6) | - (data->fan_div[0] << 4) | - data->fan_ctl)); - break; - default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - -EXIT: - mutex_unlock(&data->update_lock); - return count; -} - -/* --------------------------------------------------------------------- - * PWM sysfs interfaces - * ix = [0-1] - * --------------------------------------------------------------------- */ - -#define SHOW_PWM 0 -#define SHOW_SET_PWM_ENABLE 1 -#define SHOW_SET_PWM_FREQ 2 -#define SHOW_SET_PWM_AUTO_CHANNELS_TEMP 3 - -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int res; - - switch (fn) { - case SHOW_PWM: - res = data->pwm[ix]; - break; - case SHOW_SET_PWM_ENABLE: - res = ((data->pwm_ctl[ix] >> 3) & 1) ? 2 : 0; - break; - case SHOW_SET_PWM_FREQ: - res = 90000 >> (data->pwm_clk & 7); - break; - case SHOW_SET_PWM_AUTO_CHANNELS_TEMP: - res = (data->pwm_ctl[ix] & 7) + 1; - break; - default: - res = 0; - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - - return sprintf(buf, "%d\n", res); -} - -static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int fn = sensor_attr_2->nr; - int tmp, reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - switch (fn) { - case SHOW_SET_PWM_ENABLE: - /* sync the data cache */ - reg = vt1211_read8(data, VT1211_REG_FAN_DIV); - data->fan_div[0] = (reg >> 4) & 3; - data->fan_div[1] = (reg >> 6) & 3; - data->fan_ctl = reg & 0xf; - reg = vt1211_read8(data, VT1211_REG_PWM_CTL); - data->pwm_ctl[0] = reg & 0xf; - data->pwm_ctl[1] = (reg >> 4) & 0xf; - switch (val) { - case 0: - data->pwm_ctl[ix] &= 7; - /* - * disable SmartGuardian if both PWM outputs are - * disabled - */ - if ((data->pwm_ctl[ix ^ 1] & 1) == 0) - data->fan_ctl &= 0xe; - break; - case 2: - data->pwm_ctl[ix] |= 8; - data->fan_ctl |= 1; - break; - default: - count = -EINVAL; - dev_warn(dev, "pwm mode %ld not supported. " - "Choose one of 0 or 2.\n", val); - goto EXIT; - } - vt1211_write8(data, VT1211_REG_PWM_CTL, - ((data->pwm_ctl[1] << 4) | - data->pwm_ctl[0])); - vt1211_write8(data, VT1211_REG_FAN_DIV, - ((data->fan_div[1] << 6) | - (data->fan_div[0] << 4) | - data->fan_ctl)); - break; - case SHOW_SET_PWM_FREQ: - val = 135000 / SENSORS_LIMIT(val, 135000 >> 7, 135000); - /* calculate tmp = log2(val) */ - tmp = 0; - for (val >>= 1; val > 0; val >>= 1) - tmp++; - /* sync the data cache */ - reg = vt1211_read8(data, VT1211_REG_PWM_CLK); - data->pwm_clk = (reg & 0xf8) | tmp; - vt1211_write8(data, VT1211_REG_PWM_CLK, data->pwm_clk); - break; - case SHOW_SET_PWM_AUTO_CHANNELS_TEMP: - if (val < 1 || val > 7) { - count = -EINVAL; - dev_warn(dev, "temp channel %ld not supported. " - "Choose a value between 1 and 7.\n", val); - goto EXIT; - } - if (!ISTEMP(val - 1, data->uch_config)) { - count = -EINVAL; - dev_warn(dev, "temp channel %ld is not available.\n", - val); - goto EXIT; - } - /* sync the data cache */ - reg = vt1211_read8(data, VT1211_REG_PWM_CTL); - data->pwm_ctl[0] = reg & 0xf; - data->pwm_ctl[1] = (reg >> 4) & 0xf; - data->pwm_ctl[ix] = (data->pwm_ctl[ix] & 8) | (val - 1); - vt1211_write8(data, VT1211_REG_PWM_CTL, - ((data->pwm_ctl[1] << 4) | data->pwm_ctl[0])); - break; - default: - dev_dbg(dev, "Unknown attr fetch (%d)\n", fn); - } - -EXIT: - mutex_unlock(&data->update_lock); - return count; -} - -/* --------------------------------------------------------------------- - * PWM auto point definitions - * ix = [0-1] - * ap = [0-3] - * --------------------------------------------------------------------- */ - -/* - * pwm[ix+1]_auto_point[ap+1]_temp mapping table: - * Note that there is only a single set of temp auto points that controls both - * PWM controllers. We still create 2 sets of sysfs files to make it look - * more consistent even though they map to the same registers. - * - * ix ap : description - * ------------------- - * 0 0 : pwm1/2 off temperature (pwm_auto_temp[0]) - * 0 1 : pwm1/2 low speed temperature (pwm_auto_temp[1]) - * 0 2 : pwm1/2 high speed temperature (pwm_auto_temp[2]) - * 0 3 : pwm1/2 full speed temperature (pwm_auto_temp[3]) - * 1 0 : pwm1/2 off temperature (pwm_auto_temp[0]) - * 1 1 : pwm1/2 low speed temperature (pwm_auto_temp[1]) - * 1 2 : pwm1/2 high speed temperature (pwm_auto_temp[2]) - * 1 3 : pwm1/2 full speed temperature (pwm_auto_temp[3]) - */ - -static ssize_t show_pwm_auto_point_temp(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int ap = sensor_attr_2->nr; - - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->pwm_ctl[ix] & 7, - data->pwm_auto_temp[ap])); -} - -static ssize_t set_pwm_auto_point_temp(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int ap = sensor_attr_2->nr; - int reg; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - - mutex_lock(&data->update_lock); - - /* sync the data cache */ - reg = vt1211_read8(data, VT1211_REG_PWM_CTL); - data->pwm_ctl[0] = reg & 0xf; - data->pwm_ctl[1] = (reg >> 4) & 0xf; - - data->pwm_auto_temp[ap] = TEMP_TO_REG(data->pwm_ctl[ix] & 7, val); - vt1211_write8(data, VT1211_REG_PWM_AUTO_TEMP(ap), - data->pwm_auto_temp[ap]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* - * pwm[ix+1]_auto_point[ap+1]_pwm mapping table: - * Note that the PWM auto points 0 & 3 are hard-wired in the VT1211 and can't - * be changed. - * - * ix ap : description - * ------------------- - * 0 0 : pwm1 off (pwm_auto_pwm[0][0], hard-wired to 0) - * 0 1 : pwm1 low speed duty cycle (pwm_auto_pwm[0][1]) - * 0 2 : pwm1 high speed duty cycle (pwm_auto_pwm[0][2]) - * 0 3 : pwm1 full speed (pwm_auto_pwm[0][3], hard-wired to 255) - * 1 0 : pwm2 off (pwm_auto_pwm[1][0], hard-wired to 0) - * 1 1 : pwm2 low speed duty cycle (pwm_auto_pwm[1][1]) - * 1 2 : pwm2 high speed duty cycle (pwm_auto_pwm[1][2]) - * 1 3 : pwm2 full speed (pwm_auto_pwm[1][3], hard-wired to 255) - */ - -static ssize_t show_pwm_auto_point_pwm(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int ap = sensor_attr_2->nr; - - return sprintf(buf, "%d\n", data->pwm_auto_pwm[ix][ap]); -} - -static ssize_t set_pwm_auto_point_pwm(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr_2 = - to_sensor_dev_attr_2(attr); - int ix = sensor_attr_2->index; - int ap = sensor_attr_2->nr; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm_auto_pwm[ix][ap] = SENSORS_LIMIT(val, 0, 255); - vt1211_write8(data, VT1211_REG_PWM_AUTO_PWM(ix, ap), - data->pwm_auto_pwm[ix][ap]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* --------------------------------------------------------------------- - * Miscellaneous sysfs interfaces (VRM, VID, name, and (legacy) alarms) - * --------------------------------------------------------------------- */ - -static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - - return count; -} - -static ssize_t show_vid(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct vt1211_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} - -static ssize_t show_alarms(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct vt1211_data *data = vt1211_update_device(dev); - - return sprintf(buf, "%d\n", data->alarms); -} - -/* --------------------------------------------------------------------- - * Device attribute structs - * --------------------------------------------------------------------- */ - -#define SENSOR_ATTR_IN(ix) \ -{ SENSOR_ATTR_2(in##ix##_input, S_IRUGO, \ - show_in, NULL, SHOW_IN_INPUT, ix), \ - SENSOR_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \ - show_in, set_in, SHOW_SET_IN_MIN, ix), \ - SENSOR_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \ - show_in, set_in, SHOW_SET_IN_MAX, ix), \ - SENSOR_ATTR_2(in##ix##_alarm, S_IRUGO, \ - show_in, NULL, SHOW_IN_ALARM, ix) \ -} - -static struct sensor_device_attribute_2 vt1211_sysfs_in[][4] = { - SENSOR_ATTR_IN(0), - SENSOR_ATTR_IN(1), - SENSOR_ATTR_IN(2), - SENSOR_ATTR_IN(3), - SENSOR_ATTR_IN(4), - SENSOR_ATTR_IN(5) -}; - -#define IN_UNIT_ATTRS(X) \ -{ &vt1211_sysfs_in[X][0].dev_attr.attr, \ - &vt1211_sysfs_in[X][1].dev_attr.attr, \ - &vt1211_sysfs_in[X][2].dev_attr.attr, \ - &vt1211_sysfs_in[X][3].dev_attr.attr, \ - NULL \ -} - -static struct attribute *vt1211_in_attr[][5] = { - IN_UNIT_ATTRS(0), - IN_UNIT_ATTRS(1), - IN_UNIT_ATTRS(2), - IN_UNIT_ATTRS(3), - IN_UNIT_ATTRS(4), - IN_UNIT_ATTRS(5) -}; - -static const struct attribute_group vt1211_in_attr_group[] = { - { .attrs = vt1211_in_attr[0] }, - { .attrs = vt1211_in_attr[1] }, - { .attrs = vt1211_in_attr[2] }, - { .attrs = vt1211_in_attr[3] }, - { .attrs = vt1211_in_attr[4] }, - { .attrs = vt1211_in_attr[5] } -}; - -#define SENSOR_ATTR_TEMP(ix) \ -{ SENSOR_ATTR_2(temp##ix##_input, S_IRUGO, \ - show_temp, NULL, SHOW_TEMP_INPUT, ix-1), \ - SENSOR_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \ - show_temp, set_temp, SHOW_SET_TEMP_MAX, ix-1), \ - SENSOR_ATTR_2(temp##ix##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp, set_temp, SHOW_SET_TEMP_MAX_HYST, ix-1), \ - SENSOR_ATTR_2(temp##ix##_alarm, S_IRUGO, \ - show_temp, NULL, SHOW_TEMP_ALARM, ix-1) \ -} - -static struct sensor_device_attribute_2 vt1211_sysfs_temp[][4] = { - SENSOR_ATTR_TEMP(1), - SENSOR_ATTR_TEMP(2), - SENSOR_ATTR_TEMP(3), - SENSOR_ATTR_TEMP(4), - SENSOR_ATTR_TEMP(5), - SENSOR_ATTR_TEMP(6), - SENSOR_ATTR_TEMP(7), -}; - -#define TEMP_UNIT_ATTRS(X) \ -{ &vt1211_sysfs_temp[X][0].dev_attr.attr, \ - &vt1211_sysfs_temp[X][1].dev_attr.attr, \ - &vt1211_sysfs_temp[X][2].dev_attr.attr, \ - &vt1211_sysfs_temp[X][3].dev_attr.attr, \ - NULL \ -} - -static struct attribute *vt1211_temp_attr[][5] = { - TEMP_UNIT_ATTRS(0), - TEMP_UNIT_ATTRS(1), - TEMP_UNIT_ATTRS(2), - TEMP_UNIT_ATTRS(3), - TEMP_UNIT_ATTRS(4), - TEMP_UNIT_ATTRS(5), - TEMP_UNIT_ATTRS(6) -}; - -static const struct attribute_group vt1211_temp_attr_group[] = { - { .attrs = vt1211_temp_attr[0] }, - { .attrs = vt1211_temp_attr[1] }, - { .attrs = vt1211_temp_attr[2] }, - { .attrs = vt1211_temp_attr[3] }, - { .attrs = vt1211_temp_attr[4] }, - { .attrs = vt1211_temp_attr[5] }, - { .attrs = vt1211_temp_attr[6] } -}; - -#define SENSOR_ATTR_FAN(ix) \ - SENSOR_ATTR_2(fan##ix##_input, S_IRUGO, \ - show_fan, NULL, SHOW_FAN_INPUT, ix-1), \ - SENSOR_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SHOW_SET_FAN_MIN, ix-1), \ - SENSOR_ATTR_2(fan##ix##_div, S_IRUGO | S_IWUSR, \ - show_fan, set_fan, SHOW_SET_FAN_DIV, ix-1), \ - SENSOR_ATTR_2(fan##ix##_alarm, S_IRUGO, \ - show_fan, NULL, SHOW_FAN_ALARM, ix-1) - -#define SENSOR_ATTR_PWM(ix) \ - SENSOR_ATTR_2(pwm##ix, S_IRUGO, \ - show_pwm, NULL, SHOW_PWM, ix-1), \ - SENSOR_ATTR_2(pwm##ix##_enable, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, SHOW_SET_PWM_ENABLE, ix-1), \ - SENSOR_ATTR_2(pwm##ix##_auto_channels_temp, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, SHOW_SET_PWM_AUTO_CHANNELS_TEMP, ix-1) - -#define SENSOR_ATTR_PWM_FREQ(ix) \ - SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \ - show_pwm, set_pwm, SHOW_SET_PWM_FREQ, ix-1) - -#define SENSOR_ATTR_PWM_FREQ_RO(ix) \ - SENSOR_ATTR_2(pwm##ix##_freq, S_IRUGO, \ - show_pwm, NULL, SHOW_SET_PWM_FREQ, ix-1) - -#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP(ix, ap) \ - SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO | S_IWUSR, \ - show_pwm_auto_point_temp, set_pwm_auto_point_temp, \ - ap-1, ix-1) - -#define SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(ix, ap) \ - SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_temp, S_IRUGO, \ - show_pwm_auto_point_temp, NULL, \ - ap-1, ix-1) - -#define SENSOR_ATTR_PWM_AUTO_POINT_PWM(ix, ap) \ - SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO | S_IWUSR, \ - show_pwm_auto_point_pwm, set_pwm_auto_point_pwm, \ - ap-1, ix-1) - -#define SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(ix, ap) \ - SENSOR_ATTR_2(pwm##ix##_auto_point##ap##_pwm, S_IRUGO, \ - show_pwm_auto_point_pwm, NULL, \ - ap-1, ix-1) - -static struct sensor_device_attribute_2 vt1211_sysfs_fan_pwm[] = { - SENSOR_ATTR_FAN(1), - SENSOR_ATTR_FAN(2), - SENSOR_ATTR_PWM(1), - SENSOR_ATTR_PWM(2), - SENSOR_ATTR_PWM_FREQ(1), - SENSOR_ATTR_PWM_FREQ_RO(2), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 1), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 2), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 3), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP(1, 4), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 1), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 2), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 3), - SENSOR_ATTR_PWM_AUTO_POINT_TEMP_RO(2, 4), - SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 1), - SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 2), - SENSOR_ATTR_PWM_AUTO_POINT_PWM(1, 3), - SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(1, 4), - SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 1), - SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 2), - SENSOR_ATTR_PWM_AUTO_POINT_PWM(2, 3), - SENSOR_ATTR_PWM_AUTO_POINT_PWM_RO(2, 4), -}; - -static struct device_attribute vt1211_sysfs_misc[] = { - __ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm), - __ATTR(cpu0_vid, S_IRUGO, show_vid, NULL), - __ATTR(name, S_IRUGO, show_name, NULL), - __ATTR(alarms, S_IRUGO, show_alarms, NULL), -}; - -/* --------------------------------------------------------------------- - * Device registration and initialization - * --------------------------------------------------------------------- */ - -static void __devinit vt1211_init_device(struct vt1211_data *data) -{ - /* set VRM */ - data->vrm = vid_which_vrm(); - - /* Read (and initialize) UCH config */ - data->uch_config = vt1211_read8(data, VT1211_REG_UCH_CONFIG); - if (uch_config > -1) { - data->uch_config = (data->uch_config & 0x83) | - (uch_config << 2); - vt1211_write8(data, VT1211_REG_UCH_CONFIG, data->uch_config); - } - - /* - * Initialize the interrupt mode (if request at module load time). - * The VT1211 implements 3 different modes for clearing interrupts: - * 0: Clear INT when status register is read. Regenerate INT as long - * as temp stays above hysteresis limit. - * 1: Clear INT when status register is read. DON'T regenerate INT - * until temp falls below hysteresis limit and exceeds hot limit - * again. - * 2: Clear INT when temp falls below max limit. - * - * The driver only allows to force mode 0 since that's the only one - * that makes sense for 'sensors' - */ - if (int_mode == 0) { - vt1211_write8(data, VT1211_REG_TEMP1_CONFIG, 0); - vt1211_write8(data, VT1211_REG_TEMP2_CONFIG, 0); - } - - /* Fill in some hard wired values into our data struct */ - data->pwm_auto_pwm[0][3] = 255; - data->pwm_auto_pwm[1][3] = 255; -} - -static void vt1211_remove_sysfs(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - int i; - - for (i = 0; i < ARRAY_SIZE(vt1211_in_attr_group); i++) - sysfs_remove_group(&dev->kobj, &vt1211_in_attr_group[i]); - - for (i = 0; i < ARRAY_SIZE(vt1211_temp_attr_group); i++) - sysfs_remove_group(&dev->kobj, &vt1211_temp_attr_group[i]); - - for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) { - device_remove_file(dev, - &vt1211_sysfs_fan_pwm[i].dev_attr); - } - for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) - device_remove_file(dev, &vt1211_sysfs_misc[i]); -} - -static int __devinit vt1211_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct vt1211_data *data; - struct resource *res; - int i, err; - - data = kzalloc(sizeof(struct vt1211_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - dev_err(dev, "Out of memory\n"); - goto EXIT; - } - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, resource_size(res), DRVNAME)) { - err = -EBUSY; - dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, (unsigned long)res->end); - goto EXIT_KFREE; - } - data->addr = res->start; - data->name = DRVNAME; - mutex_init(&data->update_lock); - - platform_set_drvdata(pdev, data); - - /* Initialize the VT1211 chip */ - vt1211_init_device(data); - - /* Create sysfs interface files */ - for (i = 0; i < ARRAY_SIZE(vt1211_in_attr_group); i++) { - if (ISVOLT(i, data->uch_config)) { - err = sysfs_create_group(&dev->kobj, - &vt1211_in_attr_group[i]); - if (err) - goto EXIT_DEV_REMOVE; - } - } - for (i = 0; i < ARRAY_SIZE(vt1211_temp_attr_group); i++) { - if (ISTEMP(i, data->uch_config)) { - err = sysfs_create_group(&dev->kobj, - &vt1211_temp_attr_group[i]); - if (err) - goto EXIT_DEV_REMOVE; - } - } - for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_fan_pwm); i++) { - err = device_create_file(dev, - &vt1211_sysfs_fan_pwm[i].dev_attr); - if (err) - goto EXIT_DEV_REMOVE; - } - for (i = 0; i < ARRAY_SIZE(vt1211_sysfs_misc); i++) { - err = device_create_file(dev, - &vt1211_sysfs_misc[i]); - if (err) - goto EXIT_DEV_REMOVE; - } - - /* Register device */ - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - dev_err(dev, "Class registration failed (%d)\n", err); - goto EXIT_DEV_REMOVE_SILENT; - } - - return 0; - -EXIT_DEV_REMOVE: - dev_err(dev, "Sysfs interface creation failed (%d)\n", err); -EXIT_DEV_REMOVE_SILENT: - vt1211_remove_sysfs(pdev); - release_region(res->start, resource_size(res)); -EXIT_KFREE: - platform_set_drvdata(pdev, NULL); - kfree(data); -EXIT: - return err; -} - -static int __devexit vt1211_remove(struct platform_device *pdev) -{ - struct vt1211_data *data = platform_get_drvdata(pdev); - struct resource *res; - - hwmon_device_unregister(data->hwmon_dev); - vt1211_remove_sysfs(pdev); - platform_set_drvdata(pdev, NULL); - kfree(data); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, resource_size(res)); - - return 0; -} - -static struct platform_driver vt1211_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = vt1211_probe, - .remove = __devexit_p(vt1211_remove), -}; - -static int __init vt1211_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + 0x7f, - .flags = IORESOURCE_IO, - }; - int err; - - pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed (%d)\n", err); - goto EXIT; - } - - res.name = pdev->name; - err = acpi_check_resource_conflict(&res); - if (err) - goto EXIT_DEV_PUT; - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto EXIT_DEV_PUT; - } - - err = platform_device_add(pdev); - if (err) { - pr_err("Device addition failed (%d)\n", err); - goto EXIT_DEV_PUT; - } - - return 0; - -EXIT_DEV_PUT: - platform_device_put(pdev); -EXIT: - return err; -} - -static int __init vt1211_find(int sio_cip, unsigned short *address) -{ - int err = -ENODEV; - int devid; - - superio_enter(sio_cip); - - devid = force_id ? force_id : superio_inb(sio_cip, SIO_VT1211_DEVID); - if (devid != SIO_VT1211_ID) - goto EXIT; - - superio_select(sio_cip, SIO_VT1211_LDN_HWMON); - - if ((superio_inb(sio_cip, SIO_VT1211_ACTIVE) & 1) == 0) { - pr_warn("HW monitor is disabled, skipping\n"); - goto EXIT; - } - - *address = ((superio_inb(sio_cip, SIO_VT1211_BADDR) << 8) | - (superio_inb(sio_cip, SIO_VT1211_BADDR + 1))) & 0xff00; - if (*address == 0) { - pr_warn("Base address is not set, skipping\n"); - goto EXIT; - } - - err = 0; - pr_info("Found VT1211 chip at 0x%04x, revision %u\n", - *address, superio_inb(sio_cip, SIO_VT1211_DEVREV)); - -EXIT: - superio_exit(sio_cip); - return err; -} - -static int __init vt1211_init(void) -{ - int err; - unsigned short address = 0; - - err = vt1211_find(SIO_REG_CIP1, &address); - if (err) { - err = vt1211_find(SIO_REG_CIP2, &address); - if (err) - goto EXIT; - } - - if ((uch_config < -1) || (uch_config > 31)) { - err = -EINVAL; - pr_warn("Invalid UCH configuration %d. " - "Choose a value between 0 and 31.\n", uch_config); - goto EXIT; - } - - if ((int_mode < -1) || (int_mode > 0)) { - err = -EINVAL; - pr_warn("Invalid interrupt mode %d. " - "Only mode 0 is supported.\n", int_mode); - goto EXIT; - } - - err = platform_driver_register(&vt1211_driver); - if (err) - goto EXIT; - - /* Sets global pdev as a side effect */ - err = vt1211_device_add(address); - if (err) - goto EXIT_DRV_UNREGISTER; - - return 0; - -EXIT_DRV_UNREGISTER: - platform_driver_unregister(&vt1211_driver); -EXIT: - return err; -} - -static void __exit vt1211_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&vt1211_driver); -} - -MODULE_AUTHOR("Juerg Haefliger "); -MODULE_DESCRIPTION("VT1211 sensors"); -MODULE_LICENSE("GPL"); - -module_init(vt1211_init); -module_exit(vt1211_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/vt8231.c b/ANDROID_3.4.5/drivers/hwmon/vt8231.c deleted file mode 100644 index 386a8453..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/vt8231.c +++ /dev/null @@ -1,1082 +0,0 @@ -/* - * vt8231.c - Part of lm_sensors, Linux kernel modules - * for hardware monitoring - * - * Copyright (c) 2005 Roger Lucas - * Copyright (c) 2002 Mark D. Studebaker - * Aaron M. Marsh - * - * 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 VIA VT8231 South Bridge embedded sensors - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int force_addr; -module_param(force_addr, int, 0); -MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors"); - -static struct platform_device *pdev; - -#define VT8231_EXTENT 0x80 -#define VT8231_BASE_REG 0x70 -#define VT8231_ENABLE_REG 0x74 - -/* - * The VT8231 registers - * - * The reset value for the input channel configuration is used (Reg 0x4A=0x07) - * which sets the selected inputs marked with '*' below if multiple options are - * possible: - * - * Voltage Mode Temperature Mode - * Sensor Linux Id Linux Id VIA Id - * -------- -------- -------- ------ - * CPU Diode N/A temp1 0 - * UIC1 in0 temp2 * 1 - * UIC2 in1 * temp3 2 - * UIC3 in2 * temp4 3 - * UIC4 in3 * temp5 4 - * UIC5 in4 * temp6 5 - * 3.3V in5 N/A - * - * Note that the BIOS may set the configuration register to a different value - * to match the motherboard configuration. - */ - -/* fans numbered 0-1 */ -#define VT8231_REG_FAN_MIN(nr) (0x3b + (nr)) -#define VT8231_REG_FAN(nr) (0x29 + (nr)) - -/* Voltage inputs numbered 0-5 */ - -static const u8 regvolt[] = { 0x21, 0x22, 0x23, 0x24, 0x25, 0x26 }; -static const u8 regvoltmax[] = { 0x3d, 0x2b, 0x2d, 0x2f, 0x31, 0x33 }; -static const u8 regvoltmin[] = { 0x3e, 0x2c, 0x2e, 0x30, 0x32, 0x34 }; - -/* - * Temperatures are numbered 1-6 according to the Linux kernel specification. - * - * In the VIA datasheet, however, the temperatures are numbered from zero. - * Since it is important that this driver can easily be compared to the VIA - * datasheet, we will use the VIA numbering within this driver and map the - * kernel sysfs device name to the VIA number in the sysfs callback. - */ - -#define VT8231_REG_TEMP_LOW01 0x49 -#define VT8231_REG_TEMP_LOW25 0x4d - -static const u8 regtemp[] = { 0x1f, 0x21, 0x22, 0x23, 0x24, 0x25 }; -static const u8 regtempmax[] = { 0x39, 0x3d, 0x2b, 0x2d, 0x2f, 0x31 }; -static const u8 regtempmin[] = { 0x3a, 0x3e, 0x2c, 0x2e, 0x30, 0x32 }; - -#define TEMP_FROM_REG(reg) (((253 * 4 - (reg)) * 550 + 105) / 210) -#define TEMP_MAXMIN_FROM_REG(reg) (((253 - (reg)) * 2200 + 105) / 210) -#define TEMP_MAXMIN_TO_REG(val) (253 - ((val) * 210 + 1100) / 2200) - -#define VT8231_REG_CONFIG 0x40 -#define VT8231_REG_ALARM1 0x41 -#define VT8231_REG_ALARM2 0x42 -#define VT8231_REG_FANDIV 0x47 -#define VT8231_REG_UCH_CONFIG 0x4a -#define VT8231_REG_TEMP1_CONFIG 0x4b -#define VT8231_REG_TEMP2_CONFIG 0x4c - -/* - * temps 0-5 as numbered in VIA datasheet - see later for mapping to Linux - * numbering - */ -#define ISTEMP(i, ch_config) ((i) == 0 ? 1 : \ - ((ch_config) >> ((i)+1)) & 0x01) -/* voltages 0-5 */ -#define ISVOLT(i, ch_config) ((i) == 5 ? 1 : \ - !(((ch_config) >> ((i)+2)) & 0x01)) - -#define DIV_FROM_REG(val) (1 << (val)) - -/* - * NB The values returned here are NOT temperatures. The calibration curves - * for the thermistor curves are board-specific and must go in the - * sensors.conf file. Temperature sensors are actually ten bits, but the - * VIA datasheet only considers the 8 MSBs obtained from the regtemp[] - * register. The temperature value returned should have a magnitude of 3, - * so we use the VIA scaling as the "true" scaling and use the remaining 2 - * LSBs as fractional precision. - * - * All the on-chip hardware temperature comparisons for the alarms are only - * 8-bits wide, and compare against the 8 MSBs of the temperature. The bits - * in the registers VT8231_REG_TEMP_LOW01 and VT8231_REG_TEMP_LOW25 are - * ignored. - */ - -/* - ****** FAN RPM CONVERSIONS ******** - * This chip saturates back at 0, not at 255 like many the other chips. - * So, 0 means 0 RPM - */ -static inline u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 0; - return SENSORS_LIMIT(1310720 / (rpm * div), 1, 255); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div))) - -struct vt8231_data { - unsigned short addr; - const char *name; - - struct mutex update_lock; - struct device *hwmon_dev; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[6]; /* Register value */ - u8 in_max[6]; /* Register value */ - u8 in_min[6]; /* Register value */ - u16 temp[6]; /* Register value 10 bit, right aligned */ - u8 temp_max[6]; /* Register value */ - u8 temp_min[6]; /* Register value */ - u8 fan[2]; /* Register value */ - u8 fan_min[2]; /* Register value */ - u8 fan_div[2]; /* Register encoding, shifted right */ - u16 alarms; /* Register encoding */ - u8 uch_config; -}; - -static struct pci_dev *s_bridge; -static int vt8231_probe(struct platform_device *pdev); -static int __devexit vt8231_remove(struct platform_device *pdev); -static struct vt8231_data *vt8231_update_device(struct device *dev); -static void vt8231_init_device(struct vt8231_data *data); - -static inline int vt8231_read_value(struct vt8231_data *data, u8 reg) -{ - return inb_p(data->addr + reg); -} - -static inline void vt8231_write_value(struct vt8231_data *data, u8 reg, - u8 value) -{ - outb_p(value, data->addr + reg); -} - -/* following are the sysfs callback functions */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - - return sprintf(buf, "%d\n", ((data->in[nr] - 3) * 10000) / 958); -} - -static ssize_t show_in_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - - return sprintf(buf, "%d\n", ((data->in_min[nr] - 3) * 10000) / 958); -} - -static ssize_t show_in_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - - return sprintf(buf, "%d\n", (((data->in_max[nr] - 3) * 10000) / 958)); -} - -static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); - vt8231_write_value(data, regvoltmin[nr], data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255); - vt8231_write_value(data, regvoltmax[nr], data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* Special case for input 5 as this has 3.3V scaling built into the chip */ -static ssize_t show_in5(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - - return sprintf(buf, "%d\n", - (((data->in[5] - 3) * 10000 * 54) / (958 * 34))); -} - -static ssize_t show_in5_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - - return sprintf(buf, "%d\n", - (((data->in_min[5] - 3) * 10000 * 54) / (958 * 34))); -} - -static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - - return sprintf(buf, "%d\n", - (((data->in_max[5] - 3) * 10000 * 54) / (958 * 34))); -} - -static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, - 0, 255); - vt8231_write_value(data, regvoltmin[5], data->in_min[5]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3, - 0, 255); - vt8231_write_value(data, regvoltmax[5], data->in_max[5]); - mutex_unlock(&data->update_lock); - return count; -} - -#define define_voltage_sysfs(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, set_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, set_in_max, offset) - -define_voltage_sysfs(0); -define_voltage_sysfs(1); -define_voltage_sysfs(2); -define_voltage_sysfs(3); -define_voltage_sysfs(4); - -static DEVICE_ATTR(in5_input, S_IRUGO, show_in5, NULL); -static DEVICE_ATTR(in5_min, S_IRUGO | S_IWUSR, show_in5_min, set_in5_min); -static DEVICE_ATTR(in5_max, S_IRUGO | S_IWUSR, show_in5_max, set_in5_max); - -/* Temperatures */ -static ssize_t show_temp0(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", data->temp[0] * 250); -} - -static ssize_t show_temp0_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", data->temp_max[0] * 1000); -} - -static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", data->temp_min[0] * 1000); -} - -static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); - vt8231_write_value(data, regtempmax[0], data->temp_max[0]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255); - vt8231_write_value(data, regtempmin[0], data->temp_min[0]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t show_temp(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr])); -} - -static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_max[nr])); -} - -static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", TEMP_MAXMIN_FROM_REG(data->temp_min[nr])); -} - -static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); - vt8231_write_value(data, regtempmax[nr], data->temp_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255); - vt8231_write_value(data, regtempmin[nr], data->temp_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Note that these map the Linux temperature sensor numbering (1-6) to the VIA - * temperature sensor numbering (0-5) - */ -#define define_temperature_sysfs(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, set_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_min, set_temp_min, offset - 1) - -static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp0, NULL); -static DEVICE_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp0_max, set_temp0_max); -static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp0_min, - set_temp0_min); - -define_temperature_sysfs(2); -define_temperature_sysfs(3); -define_temperature_sysfs(4); -define_temperature_sysfs(5); -define_temperature_sysfs(6); - -/* Fans */ -static ssize_t show_fan(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_min(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr]))); -} - -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr])); -} - -static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct vt8231_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - unsigned long val; - int nr = sensor_attr->index; - int old = vt8231_read_value(data, VT8231_REG_FANDIV); - long min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - switch (val) { - case 1: - data->fan_div[nr] = 0; - break; - case 2: - data->fan_div[nr] = 1; - break; - case 4: - data->fan_div[nr] = 2; - break; - case 8: - data->fan_div[nr] = 3; - break; - default: - dev_err(dev, "fan_div value %ld not supported. " - "Choose one of 1, 2, 4 or 8!\n", val); - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - /* Correct the fan minimum speed */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]); - - old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4); - vt8231_write_value(data, VT8231_REG_FANDIV, old); - mutex_unlock(&data->update_lock); - return count; -} - - -#define define_fan_sysfs(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \ - show_fan_div, set_fan_div, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, set_fan_min, offset - 1) - -define_fan_sysfs(1); -define_fan_sysfs(2); - -/* Alarms */ -static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int bitnr = to_sensor_dev_attr(attr)->index; - struct vt8231_data *data = vt8231_update_device(dev); - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(temp4_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(temp5_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp6_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 1); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); - -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct attribute *vt8231_attributes_temps[6][5] = { - { - &dev_attr_temp1_input.attr, - &dev_attr_temp1_max_hyst.attr, - &dev_attr_temp1_max.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp4_input.dev_attr.attr, - &sensor_dev_attr_temp4_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp4_max.dev_attr.attr, - &sensor_dev_attr_temp4_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp5_input.dev_attr.attr, - &sensor_dev_attr_temp5_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp5_max.dev_attr.attr, - &sensor_dev_attr_temp5_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_temp6_input.dev_attr.attr, - &sensor_dev_attr_temp6_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp6_max.dev_attr.attr, - &sensor_dev_attr_temp6_alarm.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group vt8231_group_temps[6] = { - { .attrs = vt8231_attributes_temps[0] }, - { .attrs = vt8231_attributes_temps[1] }, - { .attrs = vt8231_attributes_temps[2] }, - { .attrs = vt8231_attributes_temps[3] }, - { .attrs = vt8231_attributes_temps[4] }, - { .attrs = vt8231_attributes_temps[5] }, -}; - -static struct attribute *vt8231_attributes_volts[6][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 - }, { - &dev_attr_in5_input.attr, - &dev_attr_in5_min.attr, - &dev_attr_in5_max.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group vt8231_group_volts[6] = { - { .attrs = vt8231_attributes_volts[0] }, - { .attrs = vt8231_attributes_volts[1] }, - { .attrs = vt8231_attributes_volts[2] }, - { .attrs = vt8231_attributes_volts[3] }, - { .attrs = vt8231_attributes_volts[4] }, - { .attrs = vt8231_attributes_volts[5] }, -}; - -static struct attribute *vt8231_attributes[] = { - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group vt8231_group = { - .attrs = vt8231_attributes, -}; - -static struct platform_driver vt8231_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "vt8231", - }, - .probe = vt8231_probe, - .remove = __devexit_p(vt8231_remove), -}; - -static DEFINE_PCI_DEVICE_TABLE(vt8231_pci_ids) = { - { PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4) }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, vt8231_pci_ids); - -static int __devinit vt8231_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id); - -static struct pci_driver vt8231_pci_driver = { - .name = "vt8231", - .id_table = vt8231_pci_ids, - .probe = vt8231_pci_probe, -}; - -static int vt8231_probe(struct platform_device *pdev) -{ - struct resource *res; - struct vt8231_data *data; - int err = 0, i; - - /* Reserve the ISA region */ - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, VT8231_EXTENT, - vt8231_driver.driver.name)) { - dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n", - (unsigned long)res->start, (unsigned long)res->end); - return -ENODEV; - } - - data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release; - } - - platform_set_drvdata(pdev, data); - data->addr = res->start; - data->name = "vt8231"; - - mutex_init(&data->update_lock); - vt8231_init_device(data); - - /* Register sysfs hooks */ - err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group); - if (err) - goto exit_free; - - /* Must update device information to find out the config field */ - data->uch_config = vt8231_read_value(data, VT8231_REG_UCH_CONFIG); - - for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) { - if (ISTEMP(i, data->uch_config)) { - err = sysfs_create_group(&pdev->dev.kobj, - &vt8231_group_temps[i]); - if (err) - goto exit_remove_files; - } - } - - for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) { - if (ISVOLT(i, data->uch_config)) { - err = sysfs_create_group(&pdev->dev.kobj, - &vt8231_group_volts[i]); - if (err) - goto exit_remove_files; - } - } - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - return 0; - -exit_remove_files: - for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) - sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]); - - for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) - sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]); - - sysfs_remove_group(&pdev->dev.kobj, &vt8231_group); - -exit_free: - platform_set_drvdata(pdev, NULL); - kfree(data); - -exit_release: - release_region(res->start, VT8231_EXTENT); - return err; -} - -static int __devexit vt8231_remove(struct platform_device *pdev) -{ - struct vt8231_data *data = platform_get_drvdata(pdev); - int i; - - hwmon_device_unregister(data->hwmon_dev); - - for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) - sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]); - - for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) - sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]); - - sysfs_remove_group(&pdev->dev.kobj, &vt8231_group); - - release_region(data->addr, VT8231_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; -} - -static void vt8231_init_device(struct vt8231_data *data) -{ - vt8231_write_value(data, VT8231_REG_TEMP1_CONFIG, 0); - vt8231_write_value(data, VT8231_REG_TEMP2_CONFIG, 0); -} - -static struct vt8231_data *vt8231_update_device(struct device *dev) -{ - struct vt8231_data *data = dev_get_drvdata(dev); - int i; - u16 low; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - for (i = 0; i < 6; i++) { - if (ISVOLT(i, data->uch_config)) { - data->in[i] = vt8231_read_value(data, - regvolt[i]); - data->in_min[i] = vt8231_read_value(data, - regvoltmin[i]); - data->in_max[i] = vt8231_read_value(data, - regvoltmax[i]); - } - } - for (i = 0; i < 2; i++) { - data->fan[i] = vt8231_read_value(data, - VT8231_REG_FAN(i)); - data->fan_min[i] = vt8231_read_value(data, - VT8231_REG_FAN_MIN(i)); - } - - low = vt8231_read_value(data, VT8231_REG_TEMP_LOW01); - low = (low >> 6) | ((low & 0x30) >> 2) - | (vt8231_read_value(data, VT8231_REG_TEMP_LOW25) << 4); - for (i = 0; i < 6; i++) { - if (ISTEMP(i, data->uch_config)) { - data->temp[i] = (vt8231_read_value(data, - regtemp[i]) << 2) - | ((low >> (2 * i)) & 0x03); - data->temp_max[i] = vt8231_read_value(data, - regtempmax[i]); - data->temp_min[i] = vt8231_read_value(data, - regtempmin[i]); - } - } - - i = vt8231_read_value(data, VT8231_REG_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - data->alarms = vt8231_read_value(data, VT8231_REG_ALARM1) | - (vt8231_read_value(data, VT8231_REG_ALARM2) << 8); - - /* Set alarm flags correctly */ - if (!data->fan[0] && data->fan_min[0]) - data->alarms |= 0x40; - else if (data->fan[0] && !data->fan_min[0]) - data->alarms &= ~0x40; - - if (!data->fan[1] && data->fan_min[1]) - data->alarms |= 0x80; - else if (data->fan[1] && !data->fan_min[1]) - data->alarms &= ~0x80; - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static int __devinit vt8231_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + VT8231_EXTENT - 1, - .name = "vt8231", - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc("vt8231", address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - return err; -} - -static int __devinit vt8231_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) -{ - u16 address, val; - if (force_addr) { - address = force_addr & 0xff00; - dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", - address); - - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VT8231_BASE_REG, address | 1)) - return -ENODEV; - } - - if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG, - &val)) - return -ENODEV; - - address = val & ~(VT8231_EXTENT - 1); - if (address == 0) { - dev_err(&dev->dev, "base address not set - upgrade BIOS or use force_addr=0xaddr\n"); - return -ENODEV; - } - - if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_ENABLE_REG, - &val)) - return -ENODEV; - - if (!(val & 0x0001)) { - dev_warn(&dev->dev, "enabling sensors\n"); - if (PCIBIOS_SUCCESSFUL != - pci_write_config_word(dev, VT8231_ENABLE_REG, - val | 0x0001)) - return -ENODEV; - } - - if (platform_driver_register(&vt8231_driver)) - goto exit; - - /* Sets global pdev as a side effect */ - if (vt8231_device_add(address)) - goto exit_unregister; - - /* - * Always return failure here. This is to allow other drivers to bind - * to this pci device. We don't really want to have control over the - * pci device, we only wanted to read as few register values from it. - */ - - /* - * We do, however, mark ourselves as using the PCI device to stop it - * getting unloaded. - */ - s_bridge = pci_dev_get(dev); - return -ENODEV; - -exit_unregister: - platform_driver_unregister(&vt8231_driver); -exit: - return -ENODEV; -} - -static int __init sm_vt8231_init(void) -{ - return pci_register_driver(&vt8231_pci_driver); -} - -static void __exit sm_vt8231_exit(void) -{ - pci_unregister_driver(&vt8231_pci_driver); - if (s_bridge != NULL) { - platform_device_unregister(pdev); - platform_driver_unregister(&vt8231_driver); - pci_dev_put(s_bridge); - s_bridge = NULL; - } -} - -MODULE_AUTHOR("Roger Lucas "); -MODULE_DESCRIPTION("VT8231 sensors"); -MODULE_LICENSE("GPL"); - -module_init(sm_vt8231_init); -module_exit(sm_vt8231_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83627ehf.c b/ANDROID_3.4.5/drivers/hwmon/w83627ehf.c deleted file mode 100644 index 54922ed1..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83627ehf.c +++ /dev/null @@ -1,2800 +0,0 @@ -/* - * w83627ehf - Driver for the hardware monitoring functionality of - * the Winbond W83627EHF Super-I/O chip - * Copyright (C) 2005-2011 Jean Delvare - * Copyright (C) 2006 Yuan Mu (Winbond), - * Rudolf Marek - * David Hubbard - * Daniel J Blueman - * Copyright (C) 2010 Sheng-Yuan Huang (Nuvoton) (PS00) - * - * Shamelessly ripped from the w83627hf driver - * Copyright (C) 2003 Mark Studebaker - * - * Thanks to Leon Moonen, Steve Cliffe and Grant Coady for their help - * in testing and debugging this driver. - * - * This driver also supports the W83627EHG, which is the lead-free - * version of the W83627EHF. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (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 - * w83627ehf 10 5 4 3 0x8850 0x88 0x5ca3 - * 0x8860 0xa1 - * w83627dhg 9 5 4 3 0xa020 0xc1 0x5ca3 - * w83627dhg-p 9 5 4 3 0xb070 0xc1 0x5ca3 - * w83627uhg 8 2 2 3 0xa230 0xc1 0x5ca3 - * w83667hg 9 5 3 3 0xa510 0xc1 0x5ca3 - * w83667hg-b 9 5 3 4 0xb350 0xc1 0x5ca3 - * nct6775f 9 4 3 9 0xb470 0xc1 0x5ca3 - * nct6776f 9 5 3 9 0xC330 0xc1 0x5ca3 - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lm75.h" - -enum kinds { - w83627ehf, w83627dhg, w83627dhg_p, w83627uhg, - w83667hg, w83667hg_b, nct6775, nct6776, -}; - -/* used to set data->name = w83627ehf_device_names[data->sio_kind] */ -static const char * const w83627ehf_device_names[] = { - "w83627ehf", - "w83627dhg", - "w83627dhg", - "w83627uhg", - "w83667hg", - "w83667hg", - "nct6775", - "nct6776", -}; - -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 "w83627ehf" - -/* - * Super-I/O constants and functions - */ - -#define W83627EHF_LD_HWM 0x0b -#define W83667HG_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_W83627EHF_ID 0x8850 -#define SIO_W83627EHG_ID 0x8860 -#define SIO_W83627DHG_ID 0xa020 -#define SIO_W83627DHG_P_ID 0xb070 -#define SIO_W83627UHG_ID 0xa230 -#define SIO_W83667HG_ID 0xa510 -#define SIO_W83667HG_B_ID 0xb350 -#define SIO_NCT6775_ID 0xb470 -#define SIO_NCT6776_ID 0xc330 -#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 W83627EHF_REG_BANK 0x4E -#define W83627EHF_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 - */ - -static const u16 W83627EHF_REG_FAN[] = { 0x28, 0x29, 0x2a, 0x3f, 0x553 }; -static const u16 W83627EHF_REG_FAN_MIN[] = { 0x3b, 0x3c, 0x3d, 0x3e, 0x55c }; - -/* The W83627EHF registers for nr=7,8,9 are in bank 5 */ -#define W83627EHF_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ - (0x554 + (((nr) - 7) * 2))) -#define W83627EHF_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ - (0x555 + (((nr) - 7) * 2))) -#define W83627EHF_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ - (0x550 + (nr) - 7)) - -static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250, 0x7e }; -static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253, 0 }; -static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255, 0 }; -static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 }; - -/* Fan clock dividers are spread over the following five registers */ -#define W83627EHF_REG_FANDIV1 0x47 -#define W83627EHF_REG_FANDIV2 0x4B -#define W83627EHF_REG_VBAT 0x5D -#define W83627EHF_REG_DIODE 0x59 -#define W83627EHF_REG_SMI_OVT 0x4C - -/* NCT6775F has its own fan divider registers */ -#define NCT6775_REG_FANDIV1 0x506 -#define NCT6775_REG_FANDIV2 0x507 -#define NCT6775_REG_FAN_DEBOUNCE 0xf0 - -#define W83627EHF_REG_ALARM1 0x459 -#define W83627EHF_REG_ALARM2 0x45A -#define W83627EHF_REG_ALARM3 0x45B - -#define W83627EHF_REG_CASEOPEN_DET 0x42 /* SMI STATUS #2 */ -#define W83627EHF_REG_CASEOPEN_CLR 0x46 /* SMI MASK #3 */ - -/* SmartFan registers */ -#define W83627EHF_REG_FAN_STEPUP_TIME 0x0f -#define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e - -/* DC or PWM output fan configuration */ -static const u8 W83627EHF_REG_PWM_ENABLE[] = { - 0x04, /* SYS FAN0 output mode and PWM mode */ - 0x04, /* CPU FAN0 output mode and PWM mode */ - 0x12, /* AUX FAN mode */ - 0x62, /* CPU FAN1 mode */ -}; - -static const u8 W83627EHF_PWM_MODE_SHIFT[] = { 0, 1, 0, 6 }; -static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 }; - -/* FAN Duty Cycle, be used to control */ -static const u16 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 }; -static const u16 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 }; -static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 }; - -/* Advanced Fan control, some values are common for all fans */ -static const u16 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 }; -static const u16 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 }; -static const u16 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 }; - -static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[] - = { 0xff, 0x67, 0xff, 0x69 }; -static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[] - = { 0xff, 0x68, 0xff, 0x6a }; - -static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b }; -static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] - = { 0x68, 0x6a, 0x6c }; - -static const u16 W83627EHF_REG_TEMP_OFFSET[] = { 0x454, 0x455, 0x456 }; - -static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 }; -static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 }; -static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 }; -static const u16 NCT6775_REG_FAN_START_OUTPUT[] = { 0x106, 0x206, 0x306 }; -static const u16 NCT6775_REG_FAN_STOP_TIME[] = { 0x107, 0x207, 0x307 }; -static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309 }; -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[] = { 0x630, 0x632, 0x634, 0x636, 0x638 }; -static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642}; - -static const u16 NCT6775_REG_TEMP[] - = { 0x27, 0x150, 0x250, 0x73, 0x75, 0x77, 0x62b, 0x62c, 0x62d }; -static const u16 NCT6775_REG_TEMP_CONFIG[] - = { 0, 0x152, 0x252, 0, 0, 0, 0x628, 0x629, 0x62A }; -static const u16 NCT6775_REG_TEMP_HYST[] - = { 0x3a, 0x153, 0x253, 0, 0, 0, 0x673, 0x678, 0x67D }; -static const u16 NCT6775_REG_TEMP_OVER[] - = { 0x39, 0x155, 0x255, 0, 0, 0, 0x672, 0x677, 0x67C }; -static const u16 NCT6775_REG_TEMP_SOURCE[] - = { 0x621, 0x622, 0x623, 0x100, 0x200, 0x300, 0x624, 0x625, 0x626 }; - -static const char *const w83667hg_b_temp_label[] = { - "SYSTIN", - "CPUTIN", - "AUXTIN", - "AMDTSI", - "PECI Agent 1", - "PECI Agent 2", - "PECI Agent 3", - "PECI Agent 4" -}; - -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" -}; - -#define NUM_REG_TEMP ARRAY_SIZE(NCT6775_REG_TEMP) - -static int is_word_sized(u16 reg) -{ - return ((((reg & 0xff00) == 0x100 - || (reg & 0xff00) == 0x200) - && ((reg & 0x00ff) == 0x50 - || (reg & 0x00ff) == 0x53 - || (reg & 0x00ff) == 0x55)) - || (reg & 0xfff0) == 0x630 - || reg == 0x640 || reg == 0x642 - || ((reg & 0xfff0) == 0x650 - && (reg & 0x000f) >= 0x06) - || reg == 0x73 || reg == 0x75 || reg == 0x77 - ); -} - -/* - * Conversions - */ - -/* 1 is PWM mode, output in ms */ -static inline unsigned int step_time_from_reg(u8 reg, u8 mode) -{ - return mode ? 100 * reg : 400 * reg; -} - -static inline u8 step_time_to_reg(unsigned int msec, u8 mode) -{ - return SENSORS_LIMIT((mode ? (msec + 50) / 100 : - (msec + 200) / 400), 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_common[10] = { - 800, 800, 1600, 1600, 800, 800, 800, 1600, 1600, 800 -}; -static const u16 scale_in_w83627uhg[9] = { - 800, 800, 3328, 3424, 800, 800, 0, 3328, 3400 -}; - -static inline long in_from_reg(u8 reg, u8 nr, const u16 *scale_in) -{ - return DIV_ROUND_CLOSEST(reg * scale_in[nr], 100); -} - -static inline u8 in_to_reg(u32 val, u8 nr, const u16 *scale_in) -{ - return SENSORS_LIMIT(DIV_ROUND_CLOSEST(val * 100, scale_in[nr]), 0, - 255); -} - -/* - * Data structures and manipulation thereof - */ - -struct w83627ehf_data { - int addr; /* IO base of hw monitor block */ - const char *name; - - struct device *hwmon_dev; - struct mutex lock; - - u16 reg_temp[NUM_REG_TEMP]; - u16 reg_temp_over[NUM_REG_TEMP]; - u16 reg_temp_hyst[NUM_REG_TEMP]; - u16 reg_temp_config[NUM_REG_TEMP]; - u8 temp_src[NUM_REG_TEMP]; - const char * const *temp_label; - - const u16 *REG_PWM; - const u16 *REG_TARGET; - const u16 *REG_FAN; - const u16 *REG_FAN_MIN; - const u16 *REG_FAN_START_OUTPUT; - const u16 *REG_FAN_STOP_OUTPUT; - const u16 *REG_FAN_STOP_TIME; - const u16 *REG_FAN_MAX_OUTPUT; - const u16 *REG_FAN_STEP_OUTPUT; - const u16 *scale_in; - - 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[10]; /* Register value */ - u8 in_max[10]; /* Register value */ - u8 in_min[10]; /* Register value */ - unsigned int rpm[5]; - u16 fan_min[5]; - u8 fan_div[5]; - 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_type[3]; - s8 temp_offset[3]; - s16 temp[9]; - s16 temp_max[9]; - s16 temp_max_hyst[9]; - u32 alarms; - u8 caseopen; - - u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ - u8 pwm_enable[4]; /* 1->manual - * 2->thermal cruise mode (also called SmartFan I) - * 3->fan speed cruise mode - * 4->variable thermal cruise (also called - * SmartFan III) - * 5->enhanced variable thermal cruise (also called - * SmartFan IV) - */ - u8 pwm_enable_orig[4]; /* original value of pwm_enable */ - u8 pwm_num; /* number of pwm */ - u8 pwm[4]; - u8 target_temp[4]; - u8 tolerance[4]; - - u8 fan_start_output[4]; /* minimum fan speed when spinning up */ - u8 fan_stop_output[4]; /* minimum fan speed when spinning down */ - u8 fan_stop_time[4]; /* time at minimum before disabling fan */ - u8 fan_max_output[4]; /* maximum fan speed */ - u8 fan_step_output[4]; /* rate of change output value */ - - u8 vid; - u8 vrm; - - u16 have_temp; - u16 have_temp_offset; - u8 in6_skip:1; - u8 temp3_val_only:1; -}; - -struct w83627ehf_sio_data { - int sioreg; - enum kinds kind; -}; - -/* - * 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 w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg) -{ - u8 bank = reg >> 8; - if (data->bank != bank) { - outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET); - outb_p(bank, data->addr + DATA_REG_OFFSET); - data->bank = bank; - } -} - -static u16 w83627ehf_read_value(struct w83627ehf_data *data, u16 reg) -{ - int res, word_sized = is_word_sized(reg); - - mutex_lock(&data->lock); - - w83627ehf_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 w83627ehf_write_value(struct w83627ehf_data *data, u16 reg, - u16 value) -{ - int word_sized = is_word_sized(reg); - - mutex_lock(&data->lock); - - w83627ehf_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 w83627ehf_read_temp(struct w83627ehf_data *data, u16 reg) -{ - u16 res; - - res = w83627ehf_read_value(data, reg); - if (!is_word_sized(reg)) - res <<= 8; - - return res; -} - -static int w83627ehf_write_temp(struct w83627ehf_data *data, u16 reg, - u16 value) -{ - if (!is_word_sized(reg)) - value >>= 8; - return w83627ehf_write_value(data, reg, value); -} - -/* This function assumes that the caller holds data->update_lock */ -static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr) -{ - u8 reg; - - switch (nr) { - case 0: - reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x70) - | (data->fan_div[0] & 0x7); - w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg); - break; - case 1: - reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x7) - | ((data->fan_div[1] << 4) & 0x70); - w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg); - case 2: - reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x70) - | (data->fan_div[2] & 0x7); - w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg); - break; - case 3: - reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x7) - | ((data->fan_div[3] << 4) & 0x70); - w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg); - break; - } -} - -/* This function assumes that the caller holds data->update_lock */ -static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr) -{ - u8 reg; - - switch (nr) { - case 0: - reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0xcf) - | ((data->fan_div[0] & 0x03) << 4); - /* fan5 input control bit is write only, compute the value */ - reg |= (data->has_fan & (1 << 4)) ? 1 : 0; - w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg); - reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xdf) - | ((data->fan_div[0] & 0x04) << 3); - w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); - break; - case 1: - reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0x3f) - | ((data->fan_div[1] & 0x03) << 6); - /* fan5 input control bit is write only, compute the value */ - reg |= (data->has_fan & (1 << 4)) ? 1 : 0; - w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg); - reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xbf) - | ((data->fan_div[1] & 0x04) << 4); - w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); - break; - case 2: - reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV2) & 0x3f) - | ((data->fan_div[2] & 0x03) << 6); - w83627ehf_write_value(data, W83627EHF_REG_FANDIV2, reg); - reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0x7f) - | ((data->fan_div[2] & 0x04) << 5); - w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg); - break; - case 3: - reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0xfc) - | (data->fan_div[3] & 0x03); - w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg); - reg = (w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT) & 0x7f) - | ((data->fan_div[3] & 0x04) << 5); - w83627ehf_write_value(data, W83627EHF_REG_SMI_OVT, reg); - break; - case 4: - reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0x73) - | ((data->fan_div[4] & 0x03) << 2) - | ((data->fan_div[4] & 0x04) << 5); - w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg); - break; - } -} - -static void w83627ehf_write_fan_div_common(struct device *dev, - struct w83627ehf_data *data, int nr) -{ - struct w83627ehf_sio_data *sio_data = dev->platform_data; - - if (sio_data->kind == nct6776) - ; /* no dividers, do nothing */ - else if (sio_data->kind == nct6775) - nct6775_write_fan_div(data, nr); - else - w83627ehf_write_fan_div(data, nr); -} - -static void nct6775_update_fan_div(struct w83627ehf_data *data) -{ - u8 i; - - i = w83627ehf_read_value(data, NCT6775_REG_FANDIV1); - data->fan_div[0] = i & 0x7; - data->fan_div[1] = (i & 0x70) >> 4; - i = w83627ehf_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 w83627ehf_update_fan_div(struct w83627ehf_data *data) -{ - int i; - - i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = (i >> 6) & 0x03; - i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV2); - data->fan_div[2] = (i >> 6) & 0x03; - i = w83627ehf_read_value(data, W83627EHF_REG_VBAT); - data->fan_div[0] |= (i >> 3) & 0x04; - data->fan_div[1] |= (i >> 4) & 0x04; - data->fan_div[2] |= (i >> 5) & 0x04; - if (data->has_fan & ((1 << 3) | (1 << 4))) { - i = w83627ehf_read_value(data, W83627EHF_REG_DIODE); - data->fan_div[3] = i & 0x03; - data->fan_div[4] = ((i >> 2) & 0x03) - | ((i >> 5) & 0x04); - } - if (data->has_fan & (1 << 3)) { - i = w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT); - data->fan_div[3] |= (i >> 5) & 0x04; - } -} - -static void w83627ehf_update_fan_div_common(struct device *dev, - struct w83627ehf_data *data) -{ - struct w83627ehf_sio_data *sio_data = dev->platform_data; - - if (sio_data->kind == nct6776) - ; /* no dividers, do nothing */ - else if (sio_data->kind == nct6775) - nct6775_update_fan_div(data); - else - w83627ehf_update_fan_div(data); -} - -static void nct6775_update_pwm(struct w83627ehf_data *data) -{ - int i; - int pwmcfg, fanmodecfg; - - for (i = 0; i < data->pwm_num; i++) { - pwmcfg = w83627ehf_read_value(data, - W83627EHF_REG_PWM_ENABLE[i]); - fanmodecfg = w83627ehf_read_value(data, - NCT6775_REG_FAN_MODE[i]); - data->pwm_mode[i] = - ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1; - data->pwm_enable[i] = ((fanmodecfg >> 4) & 7) + 1; - data->tolerance[i] = fanmodecfg & 0x0f; - data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]); - } -} - -static void w83627ehf_update_pwm(struct w83627ehf_data *data) -{ - int i; - int pwmcfg = 0, tolerance = 0; /* shut up the compiler */ - - for (i = 0; i < data->pwm_num; i++) { - if (!(data->has_fan & (1 << i))) - continue; - - /* pwmcfg, tolerance mapped for i=0, i=1 to same reg */ - if (i != 1) { - pwmcfg = w83627ehf_read_value(data, - W83627EHF_REG_PWM_ENABLE[i]); - tolerance = w83627ehf_read_value(data, - W83627EHF_REG_TOLERANCE[i]); - } - data->pwm_mode[i] = - ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1; - data->pwm_enable[i] = ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i]) - & 3) + 1; - data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]); - - data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) & 0x0f; - } -} - -static void w83627ehf_update_pwm_common(struct device *dev, - struct w83627ehf_data *data) -{ - struct w83627ehf_sio_data *sio_data = dev->platform_data; - - if (sio_data->kind == nct6775 || sio_data->kind == nct6776) - nct6775_update_pwm(data); - else - w83627ehf_update_pwm(data); -} - -static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct w83627ehf_sio_data *sio_data = dev->platform_data; - - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ/2) - || !data->valid) { - /* Fan clock dividers */ - w83627ehf_update_fan_div_common(dev, data); - - /* Measured voltages and limits */ - for (i = 0; i < data->in_num; i++) { - if ((i == 6) && data->in6_skip) - continue; - - data->in[i] = w83627ehf_read_value(data, - W83627EHF_REG_IN(i)); - data->in_min[i] = w83627ehf_read_value(data, - W83627EHF_REG_IN_MIN(i)); - data->in_max[i] = w83627ehf_read_value(data, - W83627EHF_REG_IN_MAX(i)); - } - - /* Measured fan speeds and limits */ - for (i = 0; i < 5; i++) { - u16 reg; - - if (!(data->has_fan & (1 << i))) - continue; - - reg = w83627ehf_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] = w83627ehf_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 || (sio_data->kind == nct6775 - && 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]++; - w83627ehf_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) - w83627ehf_write_value(data, - data->REG_FAN_MIN[i], - (data->fan_min[i] /= 2)); - } - } - - w83627ehf_update_pwm_common(dev, data); - - for (i = 0; i < data->pwm_num; i++) { - if (!(data->has_fan & (1 << i))) - continue; - - data->fan_start_output[i] = - w83627ehf_read_value(data, - data->REG_FAN_START_OUTPUT[i]); - data->fan_stop_output[i] = - w83627ehf_read_value(data, - data->REG_FAN_STOP_OUTPUT[i]); - data->fan_stop_time[i] = - w83627ehf_read_value(data, - data->REG_FAN_STOP_TIME[i]); - - if (data->REG_FAN_MAX_OUTPUT && - data->REG_FAN_MAX_OUTPUT[i] != 0xff) - data->fan_max_output[i] = - w83627ehf_read_value(data, - data->REG_FAN_MAX_OUTPUT[i]); - - if (data->REG_FAN_STEP_OUTPUT && - data->REG_FAN_STEP_OUTPUT[i] != 0xff) - data->fan_step_output[i] = - w83627ehf_read_value(data, - data->REG_FAN_STEP_OUTPUT[i]); - - data->target_temp[i] = - w83627ehf_read_value(data, - data->REG_TARGET[i]) & - (data->pwm_mode[i] == 1 ? 0x7f : 0xff); - } - - /* Measured temperatures and limits */ - for (i = 0; i < NUM_REG_TEMP; i++) { - if (!(data->have_temp & (1 << i))) - continue; - data->temp[i] = w83627ehf_read_temp(data, - data->reg_temp[i]); - if (data->reg_temp_over[i]) - data->temp_max[i] - = w83627ehf_read_temp(data, - data->reg_temp_over[i]); - if (data->reg_temp_hyst[i]) - data->temp_max_hyst[i] - = w83627ehf_read_temp(data, - data->reg_temp_hyst[i]); - if (data->have_temp_offset & (1 << i)) - data->temp_offset[i] - = w83627ehf_read_value(data, - W83627EHF_REG_TEMP_OFFSET[i]); - } - - data->alarms = w83627ehf_read_value(data, - W83627EHF_REG_ALARM1) | - (w83627ehf_read_value(data, - W83627EHF_REG_ALARM2) << 8) | - (w83627ehf_read_value(data, - W83627EHF_REG_ALARM3) << 16); - - data->caseopen = w83627ehf_read_value(data, - W83627EHF_REG_CASEOPEN_DET); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - return data; -} - -/* - * Sysfs callback functions - */ -#define show_in_reg(reg) \ -static ssize_t \ -show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr, \ - data->scale_in)); \ -} -show_in_reg(in) -show_in_reg(in_min) -show_in_reg(in_max) - -#define store_in_reg(REG, reg) \ -static ssize_t \ -store_in_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct w83627ehf_data *data = dev_get_drvdata(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - unsigned long val; \ - int err; \ - err = kstrtoul(buf, 10, &val); \ - if (err < 0) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = in_to_reg(val, nr, data->scale_in); \ - w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -store_in_reg(MIN, min) -store_in_reg(MAX, max) - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - return sprintf(buf, "%u\n", (data->alarms >> nr) & 0x01); -} - -static struct sensor_device_attribute sda_in_input[] = { - SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), - SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), - SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), -}; - -static struct sensor_device_attribute sda_in_alarm[] = { - SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), - SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), - SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), - SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), - SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), - SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 21), - SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 20), - SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16), - SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17), - SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 19), -}; - -static struct sensor_device_attribute sda_in_min[] = { - SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), - SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), - SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), - SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), - SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), - SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), - SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), - SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), - SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), - SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), -}; - -static struct sensor_device_attribute sda_in_max[] = { - SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), - SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), - SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), - SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), - SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), - SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), - SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), - SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), - SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), - SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), -}; - -static ssize_t -show_fan(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->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 w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->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 w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->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 w83627ehf_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->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) { - /* - * Only NCT6776F for now, so we know that 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 done; /* 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); - } else if ((reg = 1350000U / val) >= 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 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; - w83627ehf_write_fan_div_common(dev, data, nr); - /* Give the chip time to sample a new speed value */ - data->last_updated = jiffies; - } -done: - w83627ehf_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, 6), - SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), - SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), - SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 10), - SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 23), -}; - -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 w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]); -} - -#define show_temp_reg(addr, reg) \ -static ssize_t \ -show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->reg[nr])); \ -} -show_temp_reg(reg_temp, temp); -show_temp_reg(reg_temp_over, temp_max); -show_temp_reg(reg_temp_hyst, temp_max_hyst); - -#define store_temp_reg(addr, reg) \ -static ssize_t \ -store_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct w83627ehf_data *data = dev_get_drvdata(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - int err; \ - long val; \ - err = kstrtol(buf, 10, &val); \ - if (err < 0) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->reg[nr] = LM75_TEMP_TO_REG(val); \ - w83627ehf_write_temp(data, data->addr[nr], data->reg[nr]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} -store_temp_reg(reg_temp_over, temp_max); -store_temp_reg(reg_temp_hyst, temp_max_hyst); - -static ssize_t -show_temp_offset(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - - return sprintf(buf, "%d\n", - data->temp_offset[sensor_attr->index] * 1000); -} - -static ssize_t -store_temp_offset(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->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; - w83627ehf_write_value(data, W83627EHF_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 w83627ehf_data *data = w83627ehf_update_device(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - return sprintf(buf, "%d\n", (int)data->temp_type[nr]); -} - -static struct sensor_device_attribute sda_temp_input[] = { - SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0), - SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1), - SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2), - SENSOR_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3), - SENSOR_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4), - SENSOR_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5), - SENSOR_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6), - SENSOR_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7), - SENSOR_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8), -}; - -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), -}; - -static struct sensor_device_attribute sda_temp_max[] = { - SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 0), - SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 1), - SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 2), - SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 3), - SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 4), - SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 5), - SENSOR_ATTR(temp7_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 6), - SENSOR_ATTR(temp8_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 7), - SENSOR_ATTR(temp9_max, S_IRUGO | S_IWUSR, show_temp_max, - store_temp_max, 8), -}; - -static struct sensor_device_attribute sda_temp_max_hyst[] = { - SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 0), - SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 1), - SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 2), - SENSOR_ATTR(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 3), - SENSOR_ATTR(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 4), - SENSOR_ATTR(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 5), - SENSOR_ATTR(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 6), - SENSOR_ATTR(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 7), - SENSOR_ATTR(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst, - store_temp_max_hyst, 8), -}; - -static struct sensor_device_attribute sda_temp_alarm[] = { - SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), - SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), - SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), -}; - -static struct sensor_device_attribute sda_temp_type[] = { - SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0), - SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1), - SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2), -}; - -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), -}; - -#define show_pwm_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", data->reg[nr]); \ -} - -show_pwm_reg(pwm_mode) -show_pwm_reg(pwm_enable) -show_pwm_reg(pwm) - -static ssize_t -store_pwm_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct w83627ehf_sio_data *sio_data = dev->platform_data; - int nr = sensor_attr->index; - unsigned long val; - int err; - u16 reg; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - if (val > 1) - return -EINVAL; - - /* On NCT67766F, DC mode is only supported for pwm1 */ - if (sio_data->kind == nct6776 && nr && val != 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); - data->pwm_mode[nr] = val; - reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]); - if (!val) - reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr]; - w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - data->pwm[nr] = val; - w83627ehf_write_value(data, data->REG_PWM[nr], val); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct w83627ehf_sio_data *sio_data = dev->platform_data; - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - unsigned long val; - int err; - u16 reg; - - err = kstrtoul(buf, 10, &val); - if (err < 0) - return err; - - if (!val || (val > 4 && val != data->pwm_enable_orig[nr])) - return -EINVAL; - /* SmartFan III mode is not supported on NCT6776F */ - if (sio_data->kind == nct6776 && val == 4) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm_enable[nr] = val; - if (sio_data->kind == nct6775 || sio_data->kind == nct6776) { - reg = w83627ehf_read_value(data, - NCT6775_REG_FAN_MODE[nr]); - reg &= 0x0f; - reg |= (val - 1) << 4; - w83627ehf_write_value(data, - NCT6775_REG_FAN_MODE[nr], reg); - } else { - reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]); - reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]); - reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr]; - w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg); - } - mutex_unlock(&data->update_lock); - return count; -} - - -#define show_tol_temp(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", data->reg[nr] * 1000); \ -} - -show_tol_temp(tolerance) -show_tol_temp(target_temp) - -static ssize_t -store_target_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->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; - w83627ehf_write_value(data, data->REG_TARGET[nr], val); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_tolerance(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - struct w83627ehf_sio_data *sio_data = dev->platform_data; - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - u16 reg; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err < 0) - return err; - - /* Limit the temp to 0C - 15C */ - val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 15); - - mutex_lock(&data->update_lock); - if (sio_data->kind == nct6775 || sio_data->kind == nct6776) { - /* Limit tolerance further for NCT6776F */ - if (sio_data->kind == nct6776 && val > 7) - val = 7; - reg = w83627ehf_read_value(data, NCT6775_REG_FAN_MODE[nr]); - reg = (reg & 0xf0) | val; - w83627ehf_write_value(data, NCT6775_REG_FAN_MODE[nr], reg); - } else { - reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]); - if (nr == 1) - reg = (reg & 0x0f) | (val << 4); - else - reg = (reg & 0xf0) | val; - w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg); - } - data->tolerance[nr] = val; - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute sda_pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2), - SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 3), -}; - -static struct sensor_device_attribute sda_pwm_mode[] = { - SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode, - store_pwm_mode, 0), - SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode, - store_pwm_mode, 1), - SENSOR_ATTR(pwm3_mode, S_IWUSR | S_IRUGO, show_pwm_mode, - store_pwm_mode, 2), - SENSOR_ATTR(pwm4_mode, S_IWUSR | S_IRUGO, show_pwm_mode, - store_pwm_mode, 3), -}; - -static struct sensor_device_attribute sda_pwm_enable[] = { - SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 0), - SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 1), - SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 2), - SENSOR_ATTR(pwm4_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 3), -}; - -static struct sensor_device_attribute sda_target_temp[] = { - SENSOR_ATTR(pwm1_target, S_IWUSR | S_IRUGO, show_target_temp, - store_target_temp, 0), - SENSOR_ATTR(pwm2_target, S_IWUSR | S_IRUGO, show_target_temp, - store_target_temp, 1), - SENSOR_ATTR(pwm3_target, S_IWUSR | S_IRUGO, show_target_temp, - store_target_temp, 2), - SENSOR_ATTR(pwm4_target, S_IWUSR | S_IRUGO, show_target_temp, - store_target_temp, 3), -}; - -static struct sensor_device_attribute sda_tolerance[] = { - SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, show_tolerance, - store_tolerance, 0), - SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, show_tolerance, - store_tolerance, 1), - SENSOR_ATTR(pwm3_tolerance, S_IWUSR | S_IRUGO, show_tolerance, - store_tolerance, 2), - SENSOR_ATTR(pwm4_tolerance, S_IWUSR | S_IRUGO, show_tolerance, - store_tolerance, 3), -}; - -/* Smart Fan registers */ - -#define fan_functions(reg, REG) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", data->reg[nr]); \ -} \ -static ssize_t \ -store_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct w83627ehf_data *data = dev_get_drvdata(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - unsigned long val; \ - int err; \ - err = kstrtoul(buf, 10, &val); \ - if (err < 0) \ - return err; \ - val = SENSORS_LIMIT(val, 1, 255); \ - mutex_lock(&data->update_lock); \ - data->reg[nr] = val; \ - w83627ehf_write_value(data, data->REG_##REG[nr], val); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -fan_functions(fan_start_output, FAN_START_OUTPUT) -fan_functions(fan_stop_output, FAN_STOP_OUTPUT) -fan_functions(fan_max_output, FAN_MAX_OUTPUT) -fan_functions(fan_step_output, FAN_STEP_OUTPUT) - -#define fan_time_functions(reg, REG) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83627ehf_data *data = w83627ehf_update_device(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", \ - step_time_from_reg(data->reg[nr], \ - data->pwm_mode[nr])); \ -} \ -\ -static ssize_t \ -store_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct w83627ehf_data *data = dev_get_drvdata(dev); \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - int nr = sensor_attr->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->reg[nr] = val; \ - w83627ehf_write_value(data, data->REG_##REG[nr], val); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} \ - -fan_time_functions(fan_stop_time, FAN_STOP_TIME) - -static ssize_t show_name(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct sensor_device_attribute sda_sf3_arrays_fan4[] = { - SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, - store_fan_stop_time, 3), - SENSOR_ATTR(pwm4_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, - store_fan_start_output, 3), - SENSOR_ATTR(pwm4_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, - store_fan_stop_output, 3), - SENSOR_ATTR(pwm4_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, - store_fan_max_output, 3), - SENSOR_ATTR(pwm4_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, - store_fan_step_output, 3), -}; - -static struct sensor_device_attribute sda_sf3_arrays_fan3[] = { - SENSOR_ATTR(pwm3_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, - store_fan_stop_time, 2), - SENSOR_ATTR(pwm3_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, - store_fan_start_output, 2), - SENSOR_ATTR(pwm3_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, - store_fan_stop_output, 2), -}; - -static struct sensor_device_attribute sda_sf3_arrays[] = { - SENSOR_ATTR(pwm1_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, - store_fan_stop_time, 0), - SENSOR_ATTR(pwm2_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time, - store_fan_stop_time, 1), - SENSOR_ATTR(pwm1_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, - store_fan_start_output, 0), - SENSOR_ATTR(pwm2_start_output, S_IWUSR | S_IRUGO, show_fan_start_output, - store_fan_start_output, 1), - SENSOR_ATTR(pwm1_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, - store_fan_stop_output, 0), - SENSOR_ATTR(pwm2_stop_output, S_IWUSR | S_IRUGO, show_fan_stop_output, - store_fan_stop_output, 1), -}; - - -/* - * pwm1 and pwm3 don't support max and step settings on all chips. - * Need to check support while generating/removing attribute files. - */ -static struct sensor_device_attribute sda_sf3_max_step_arrays[] = { - SENSOR_ATTR(pwm1_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, - store_fan_max_output, 0), - SENSOR_ATTR(pwm1_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, - store_fan_step_output, 0), - SENSOR_ATTR(pwm2_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, - store_fan_max_output, 1), - SENSOR_ATTR(pwm2_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, - store_fan_step_output, 1), - SENSOR_ATTR(pwm3_max_output, S_IWUSR | S_IRUGO, show_fan_max_output, - store_fan_max_output, 2), - SENSOR_ATTR(pwm3_step_output, S_IWUSR | S_IRUGO, show_fan_step_output, - store_fan_step_output, 2), -}; - -static ssize_t -show_vid(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627ehf_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 -show_caseopen(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627ehf_data *data = w83627ehf_update_device(dev); - - return sprintf(buf, "%d\n", - !!(data->caseopen & to_sensor_dev_attr_2(attr)->index)); -} - -static ssize_t -clear_caseopen(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627ehf_data *data = dev_get_drvdata(dev); - unsigned long val; - u16 reg, mask; - - if (kstrtoul(buf, 10, &val) || val != 0) - return -EINVAL; - - mask = to_sensor_dev_attr_2(attr)->nr; - - mutex_lock(&data->update_lock); - reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR); - w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask); - w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask); - data->valid = 0; /* Force cache refresh */ - mutex_unlock(&data->update_lock); - - return count; -} - -static struct sensor_device_attribute_2 sda_caseopen[] = { - SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_caseopen, - clear_caseopen, 0x80, 0x10), - SENSOR_ATTR_2(intrusion1_alarm, S_IWUSR | S_IRUGO, show_caseopen, - clear_caseopen, 0x40, 0x40), -}; - -/* - * Driver and device management - */ - -static void w83627ehf_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 w83627ehf_data *data = dev_get_drvdata(dev); - - for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) - device_remove_file(dev, &sda_sf3_arrays[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { - struct sensor_device_attribute *attr = - &sda_sf3_max_step_arrays[i]; - if (data->REG_FAN_STEP_OUTPUT && - data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) - device_remove_file(dev, &attr->dev_attr); - } - for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) - device_remove_file(dev, &sda_sf3_arrays_fan3[i].dev_attr); - for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) - device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr); - for (i = 0; i < data->in_num; i++) { - if ((i == 6) && data->in6_skip) - continue; - device_remove_file(dev, &sda_in_input[i].dev_attr); - device_remove_file(dev, &sda_in_alarm[i].dev_attr); - device_remove_file(dev, &sda_in_min[i].dev_attr); - device_remove_file(dev, &sda_in_max[i].dev_attr); - } - 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 < data->pwm_num; i++) { - device_remove_file(dev, &sda_pwm[i].dev_attr); - device_remove_file(dev, &sda_pwm_mode[i].dev_attr); - device_remove_file(dev, &sda_pwm_enable[i].dev_attr); - device_remove_file(dev, &sda_target_temp[i].dev_attr); - device_remove_file(dev, &sda_tolerance[i].dev_attr); - } - for (i = 0; i < NUM_REG_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); - if (i == 2 && data->temp3_val_only) - continue; - device_remove_file(dev, &sda_temp_max[i].dev_attr); - device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr); - if (i > 2) - continue; - device_remove_file(dev, &sda_temp_alarm[i].dev_attr); - device_remove_file(dev, &sda_temp_type[i].dev_attr); - device_remove_file(dev, &sda_temp_offset[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 w83627ehf_init_device(struct w83627ehf_data *data, - enum kinds kind) -{ - int i; - u8 tmp, diode; - - /* Start monitoring is needed */ - tmp = w83627ehf_read_value(data, W83627EHF_REG_CONFIG); - if (!(tmp & 0x01)) - w83627ehf_write_value(data, W83627EHF_REG_CONFIG, - tmp | 0x01); - - /* Enable temperature sensors if needed */ - for (i = 0; i < NUM_REG_TEMP; i++) { - if (!(data->have_temp & (1 << i))) - continue; - if (!data->reg_temp_config[i]) - continue; - tmp = w83627ehf_read_value(data, - data->reg_temp_config[i]); - if (tmp & 0x01) - w83627ehf_write_value(data, - data->reg_temp_config[i], - tmp & 0xfe); - } - - /* Enable VBAT monitoring if needed */ - tmp = w83627ehf_read_value(data, W83627EHF_REG_VBAT); - if (!(tmp & 0x01)) - w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01); - - /* Get thermal sensor types */ - switch (kind) { - case w83627ehf: - diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE); - break; - case w83627uhg: - diode = 0x00; - break; - default: - diode = 0x70; - } - for (i = 0; i < 3; i++) { - const char *label = NULL; - - if (data->temp_label) - label = data->temp_label[data->temp_src[i]]; - - /* Digital source overrides analog type */ - if (label && strncmp(label, "PECI", 4) == 0) - data->temp_type[i] = 6; - else if (label && strncmp(label, "AMD", 3) == 0) - data->temp_type[i] = 5; - else if ((tmp & (0x02 << i))) - data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 3; - else - data->temp_type[i] = 4; /* thermistor */ - } -} - -static void w82627ehf_swap_tempreg(struct w83627ehf_data *data, - int r1, int r2) -{ - u16 tmp; - - tmp = data->temp_src[r1]; - data->temp_src[r1] = data->temp_src[r2]; - data->temp_src[r2] = tmp; - - tmp = data->reg_temp[r1]; - data->reg_temp[r1] = data->reg_temp[r2]; - data->reg_temp[r2] = tmp; - - tmp = data->reg_temp_over[r1]; - data->reg_temp_over[r1] = data->reg_temp_over[r2]; - data->reg_temp_over[r2] = tmp; - - tmp = data->reg_temp_hyst[r1]; - data->reg_temp_hyst[r1] = data->reg_temp_hyst[r2]; - data->reg_temp_hyst[r2] = tmp; - - tmp = data->reg_temp_config[r1]; - data->reg_temp_config[r1] = data->reg_temp_config[r2]; - data->reg_temp_config[r2] = tmp; -} - -static void __devinit -w83627ehf_set_temp_reg_ehf(struct w83627ehf_data *data, int n_temp) -{ - int i; - - for (i = 0; i < n_temp; i++) { - data->reg_temp[i] = W83627EHF_REG_TEMP[i]; - data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i]; - data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i]; - data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i]; - } -} - -static void __devinit -w83627ehf_check_fan_inputs(const struct w83627ehf_sio_data *sio_data, - struct w83627ehf_data *data) -{ - int fan3pin, fan4pin, fan4min, fan5pin, regval; - - /* The W83627UHG is simple, only two fan inputs, no config */ - if (sio_data->kind == w83627uhg) { - data->has_fan = 0x03; /* fan1 and fan2 */ - data->has_fan_min = 0x03; - return; - } - - superio_enter(sio_data->sioreg); - - /* fan4 and fan5 share some pins with the GPIO and serial flash */ - if (sio_data->kind == nct6775) { - /* On NCT6775, fan4 shares pins with the fdc interface */ - fan3pin = 1; - fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80); - fan4min = 0; - fan5pin = 0; - } else if (sio_data->kind == nct6776) { - bool gpok = superio_inb(sio_data->sioreg, 0x27) & 0x80; - - superio_select(sio_data->sioreg, W83627EHF_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; - } else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) { - fan3pin = 1; - fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40; - fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20; - fan4min = fan4pin; - } else { - fan3pin = 1; - fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06); - fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02); - 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 |= (fan3pin << 2); - - if (sio_data->kind == nct6775 || sio_data->kind == nct6776) { - /* - * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1 - * register - */ - data->has_fan |= (fan4pin << 3) | (fan5pin << 4); - data->has_fan_min |= (fan4min << 3) | (fan5pin << 4); - } else { - /* - * It looks like fan4 and fan5 pins can be alternatively used - * as fan on/off switches, but fan5 control is write only :/ - * We assume that if the serial interface is disabled, designers - * connected fan5 as input unless they are emitting log 1, which - * is not the default. - */ - regval = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1); - if ((regval & (1 << 2)) && fan4pin) { - data->has_fan |= (1 << 3); - data->has_fan_min |= (1 << 3); - } - if (!(regval & (1 << 1)) && fan5pin) { - data->has_fan |= (1 << 4); - data->has_fan_min |= (1 << 4); - } - } -} - -static int __devinit w83627ehf_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct w83627ehf_sio_data *sio_data = dev->platform_data; - struct w83627ehf_data *data; - struct resource *res; - u8 en_vrm10; - int i, err = 0; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, IOREGION_LENGTH, DRVNAME)) { - err = -EBUSY; - dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, - (unsigned long)res->start + IOREGION_LENGTH - 1); - goto exit; - } - - data = devm_kzalloc(&pdev->dev, sizeof(struct w83627ehf_data), - GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release; - } - - data->addr = res->start; - mutex_init(&data->lock); - mutex_init(&data->update_lock); - data->name = w83627ehf_device_names[sio_data->kind]; - platform_set_drvdata(pdev, data); - - /* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */ - data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9; - /* 667HG, NCT6775F, and NCT6776F have 3 pwms, and 627UHG has only 2 */ - switch (sio_data->kind) { - default: - data->pwm_num = 4; - break; - case w83667hg: - case w83667hg_b: - case nct6775: - case nct6776: - data->pwm_num = 3; - break; - case w83627uhg: - data->pwm_num = 2; - break; - } - - /* Default to 3 temperature inputs, code below will adjust as needed */ - data->have_temp = 0x07; - - /* Deal with temperature register setup first. */ - if (sio_data->kind == nct6775 || sio_data->kind == nct6776) { - int mask = 0; - - /* - * Display temperature sensor output only if it monitors - * a source other than one already reported. Always display - * first three temperature registers, though. - */ - for (i = 0; i < NUM_REG_TEMP; i++) { - u8 src; - - data->reg_temp[i] = NCT6775_REG_TEMP[i]; - data->reg_temp_over[i] = NCT6775_REG_TEMP_OVER[i]; - data->reg_temp_hyst[i] = NCT6775_REG_TEMP_HYST[i]; - data->reg_temp_config[i] = NCT6775_REG_TEMP_CONFIG[i]; - - src = w83627ehf_read_value(data, - NCT6775_REG_TEMP_SOURCE[i]); - src &= 0x1f; - if (src && !(mask & (1 << src))) { - data->have_temp |= 1 << i; - mask |= 1 << src; - } - - data->temp_src[i] = src; - - /* - * Now do some register swapping if index 0..2 don't - * point to SYSTIN(1), CPUIN(2), and AUXIN(3). - * Idea is to have the first three attributes - * report SYSTIN, CPUIN, and AUXIN if possible - * without overriding the basic system configuration. - */ - if (i > 0 && data->temp_src[0] != 1 - && data->temp_src[i] == 1) - w82627ehf_swap_tempreg(data, 0, i); - if (i > 1 && data->temp_src[1] != 2 - && data->temp_src[i] == 2) - w82627ehf_swap_tempreg(data, 1, i); - if (i > 2 && data->temp_src[2] != 3 - && data->temp_src[i] == 3) - w82627ehf_swap_tempreg(data, 2, i); - } - if (sio_data->kind == 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->temp_src[2] == 3) { - u8 reg; - - if (data->reg_temp_config[2]) - reg = w83627ehf_read_value(data, - data->reg_temp_config[2]); - else - reg = 0; /* Assume AUXTIN is used */ - - if (reg & 0x01) - data->have_temp &= ~(1 << 2); - else - data->in6_skip = 1; - } - data->temp_label = nct6776_temp_label; - } else { - data->temp_label = nct6775_temp_label; - } - data->have_temp_offset = data->have_temp & 0x07; - for (i = 0; i < 3; i++) { - if (data->temp_src[i] > 3) - data->have_temp_offset &= ~(1 << i); - } - } else if (sio_data->kind == w83667hg_b) { - u8 reg; - - w83627ehf_set_temp_reg_ehf(data, 4); - - /* - * Temperature sources are selected with bank 0, registers 0x49 - * and 0x4a. - */ - reg = w83627ehf_read_value(data, 0x4a); - data->temp_src[0] = reg >> 5; - reg = w83627ehf_read_value(data, 0x49); - data->temp_src[1] = reg & 0x07; - data->temp_src[2] = (reg >> 4) & 0x07; - - /* - * W83667HG-B has another temperature register at 0x7e. - * The temperature source is selected with register 0x7d. - * Support it if the source differs from already reported - * sources. - */ - reg = w83627ehf_read_value(data, 0x7d); - reg &= 0x07; - if (reg != data->temp_src[0] && reg != data->temp_src[1] - && reg != data->temp_src[2]) { - data->temp_src[3] = reg; - data->have_temp |= 1 << 3; - } - - /* - * Chip supports either AUXTIN or VIN3. Try to find out which - * one. - */ - reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]); - if (data->temp_src[2] == 2 && (reg & 0x01)) - data->have_temp &= ~(1 << 2); - - if ((data->temp_src[2] == 2 && (data->have_temp & (1 << 2))) - || (data->temp_src[3] == 2 && (data->have_temp & (1 << 3)))) - data->in6_skip = 1; - - data->temp_label = w83667hg_b_temp_label; - data->have_temp_offset = data->have_temp & 0x07; - for (i = 0; i < 3; i++) { - if (data->temp_src[i] > 2) - data->have_temp_offset &= ~(1 << i); - } - } else if (sio_data->kind == w83627uhg) { - u8 reg; - - w83627ehf_set_temp_reg_ehf(data, 3); - - /* - * Temperature sources for temp2 and temp3 are selected with - * bank 0, registers 0x49 and 0x4a. - */ - data->temp_src[0] = 0; /* SYSTIN */ - reg = w83627ehf_read_value(data, 0x49) & 0x07; - /* Adjust to have the same mapping as other source registers */ - if (reg == 0) - data->temp_src[1] = 1; - else if (reg >= 2 && reg <= 5) - data->temp_src[1] = reg + 2; - else /* should never happen */ - data->have_temp &= ~(1 << 1); - reg = w83627ehf_read_value(data, 0x4a); - data->temp_src[2] = reg >> 5; - - /* - * Skip temp3 if source is invalid or the same as temp1 - * or temp2. - */ - if (data->temp_src[2] == 2 || data->temp_src[2] == 3 || - data->temp_src[2] == data->temp_src[0] || - ((data->have_temp & (1 << 1)) && - data->temp_src[2] == data->temp_src[1])) - data->have_temp &= ~(1 << 2); - else - data->temp3_val_only = 1; /* No limit regs */ - - data->in6_skip = 1; /* No VIN3 */ - - data->temp_label = w83667hg_b_temp_label; - data->have_temp_offset = data->have_temp & 0x03; - for (i = 0; i < 3; i++) { - if (data->temp_src[i] > 1) - data->have_temp_offset &= ~(1 << i); - } - } else { - w83627ehf_set_temp_reg_ehf(data, 3); - - /* Temperature sources are fixed */ - - if (sio_data->kind == w83667hg) { - u8 reg; - - /* - * Chip supports either AUXTIN or VIN3. Try to find - * out which one. - */ - reg = w83627ehf_read_value(data, - W83627EHF_REG_TEMP_CONFIG[2]); - if (reg & 0x01) - data->have_temp &= ~(1 << 2); - else - data->in6_skip = 1; - } - data->have_temp_offset = data->have_temp & 0x07; - } - - if (sio_data->kind == nct6775) { - data->has_fan_div = true; - data->fan_from_reg = fan_from_reg16; - data->fan_from_reg_min = fan_from_reg8; - data->REG_PWM = NCT6775_REG_PWM; - data->REG_TARGET = NCT6775_REG_TARGET; - data->REG_FAN = NCT6775_REG_FAN; - data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN; - data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT; - data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT; - data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME; - data->REG_FAN_MAX_OUTPUT = NCT6775_REG_FAN_MAX_OUTPUT; - data->REG_FAN_STEP_OUTPUT = NCT6775_REG_FAN_STEP_OUTPUT; - } else if (sio_data->kind == nct6776) { - data->has_fan_div = false; - data->fan_from_reg = fan_from_reg13; - data->fan_from_reg_min = fan_from_reg13; - data->REG_PWM = NCT6775_REG_PWM; - data->REG_TARGET = NCT6775_REG_TARGET; - data->REG_FAN = NCT6775_REG_FAN; - data->REG_FAN_MIN = NCT6776_REG_FAN_MIN; - data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT; - data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT; - data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME; - } else if (sio_data->kind == w83667hg_b) { - data->has_fan_div = true; - data->fan_from_reg = fan_from_reg8; - data->fan_from_reg_min = fan_from_reg8; - data->REG_PWM = W83627EHF_REG_PWM; - data->REG_TARGET = W83627EHF_REG_TARGET; - data->REG_FAN = W83627EHF_REG_FAN; - data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN; - data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT; - data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT; - data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME; - data->REG_FAN_MAX_OUTPUT = - W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B; - data->REG_FAN_STEP_OUTPUT = - W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B; - } else { - data->has_fan_div = true; - data->fan_from_reg = fan_from_reg8; - data->fan_from_reg_min = fan_from_reg8; - data->REG_PWM = W83627EHF_REG_PWM; - data->REG_TARGET = W83627EHF_REG_TARGET; - data->REG_FAN = W83627EHF_REG_FAN; - data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN; - data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT; - data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT; - data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME; - data->REG_FAN_MAX_OUTPUT = - W83627EHF_REG_FAN_MAX_OUTPUT_COMMON; - data->REG_FAN_STEP_OUTPUT = - W83627EHF_REG_FAN_STEP_OUTPUT_COMMON; - } - - /* Setup input voltage scaling factors */ - if (sio_data->kind == w83627uhg) - data->scale_in = scale_in_w83627uhg; - else - data->scale_in = scale_in_common; - - /* Initialize the chip */ - w83627ehf_init_device(data, sio_data->kind); - - data->vrm = vid_which_vrm(); - superio_enter(sio_data->sioreg); - /* Read VID value */ - if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b || - sio_data->kind == nct6775 || sio_data->kind == nct6776) { - /* - * W83667HG has different pins for VID input and output, so - * we can get the VID input values directly at logical device D - * 0xe3. - */ - superio_select(sio_data->sioreg, W83667HG_LD_VID); - data->vid = superio_inb(sio_data->sioreg, 0xe3); - err = device_create_file(dev, &dev_attr_cpu0_vid); - if (err) - goto exit_release; - } else if (sio_data->kind != w83627uhg) { - superio_select(sio_data->sioreg, W83627EHF_LD_HWM); - if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80) { - /* - * Set VID input sensibility if needed. In theory the - * BIOS should have set it, but in practice it's not - * always the case. We only do it for the W83627EHF/EHG - * because the W83627DHG is more complex in this - * respect. - */ - if (sio_data->kind == w83627ehf) { - en_vrm10 = superio_inb(sio_data->sioreg, - SIO_REG_EN_VRM10); - if ((en_vrm10 & 0x08) && data->vrm == 90) { - dev_warn(dev, "Setting VID input " - "voltage to TTL\n"); - superio_outb(sio_data->sioreg, - SIO_REG_EN_VRM10, - en_vrm10 & ~0x08); - } else if (!(en_vrm10 & 0x08) - && data->vrm == 100) { - dev_warn(dev, "Setting VID input " - "voltage to VRM10\n"); - superio_outb(sio_data->sioreg, - SIO_REG_EN_VRM10, - en_vrm10 | 0x08); - } - } - - data->vid = superio_inb(sio_data->sioreg, - SIO_REG_VID_DATA); - if (sio_data->kind == w83627ehf) /* 6 VID pins only */ - data->vid &= 0x3f; - - err = device_create_file(dev, &dev_attr_cpu0_vid); - if (err) - goto exit_release; - } else { - dev_info(dev, "VID pins in output mode, CPU VID not " - "available\n"); - } - } - - if (fan_debounce && - (sio_data->kind == nct6775 || sio_data->kind == nct6776)) { - u8 tmp; - - superio_select(sio_data->sioreg, W83627EHF_LD_HWM); - tmp = superio_inb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE); - if (sio_data->kind == nct6776) - superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE, - 0x3e | tmp); - else - superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE, - 0x1e | tmp); - pr_info("Enabled fan debounce for chip %s\n", data->name); - } - - superio_exit(sio_data->sioreg); - - w83627ehf_check_fan_inputs(sio_data, data); - - /* Read fan clock dividers immediately */ - w83627ehf_update_fan_div_common(dev, data); - - /* Read pwm data to save original values */ - w83627ehf_update_pwm_common(dev, data); - for (i = 0; i < data->pwm_num; i++) - data->pwm_enable_orig[i] = data->pwm_enable[i]; - - /* Register sysfs hooks */ - for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) { - err = device_create_file(dev, &sda_sf3_arrays[i].dev_attr); - if (err) - goto exit_remove; - } - - for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) { - struct sensor_device_attribute *attr = - &sda_sf3_max_step_arrays[i]; - if (data->REG_FAN_STEP_OUTPUT && - data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) { - err = device_create_file(dev, &attr->dev_attr); - if (err) - goto exit_remove; - } - } - /* if fan3 and fan4 are enabled create the sf3 files for them */ - if ((data->has_fan & (1 << 2)) && data->pwm_num >= 3) - for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan3); i++) { - err = device_create_file(dev, - &sda_sf3_arrays_fan3[i].dev_attr); - if (err) - goto exit_remove; - } - if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4) - for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) { - err = device_create_file(dev, - &sda_sf3_arrays_fan4[i].dev_attr); - if (err) - goto exit_remove; - } - - for (i = 0; i < data->in_num; i++) { - if ((i == 6) && data->in6_skip) - continue; - if ((err = device_create_file(dev, &sda_in_input[i].dev_attr)) - || (err = device_create_file(dev, - &sda_in_alarm[i].dev_attr)) - || (err = device_create_file(dev, - &sda_in_min[i].dev_attr)) - || (err = device_create_file(dev, - &sda_in_max[i].dev_attr))) - goto exit_remove; - } - - for (i = 0; i < 5; i++) { - if (data->has_fan & (1 << i)) { - if ((err = device_create_file(dev, - &sda_fan_input[i].dev_attr)) - || (err = device_create_file(dev, - &sda_fan_alarm[i].dev_attr))) - goto exit_remove; - if (sio_data->kind != nct6776) { - 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; - } - if (i < data->pwm_num && - ((err = device_create_file(dev, - &sda_pwm[i].dev_attr)) - || (err = device_create_file(dev, - &sda_pwm_mode[i].dev_attr)) - || (err = device_create_file(dev, - &sda_pwm_enable[i].dev_attr)) - || (err = device_create_file(dev, - &sda_target_temp[i].dev_attr)) - || (err = device_create_file(dev, - &sda_tolerance[i].dev_attr)))) - goto exit_remove; - } - } - - for (i = 0; i < NUM_REG_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 (i == 2 && data->temp3_val_only) - continue; - if (data->reg_temp_over[i]) { - err = device_create_file(dev, - &sda_temp_max[i].dev_attr); - if (err) - goto exit_remove; - } - if (data->reg_temp_hyst[i]) { - err = device_create_file(dev, - &sda_temp_max_hyst[i].dev_attr); - if (err) - goto exit_remove; - } - if (i > 2) - continue; - if ((err = device_create_file(dev, - &sda_temp_alarm[i].dev_attr)) - || (err = device_create_file(dev, - &sda_temp_type[i].dev_attr))) - goto exit_remove; - if (data->have_temp_offset & (1 << i)) { - err = device_create_file(dev, - &sda_temp_offset[i].dev_attr); - if (err) - goto exit_remove; - } - } - - err = device_create_file(dev, &sda_caseopen[0].dev_attr); - if (err) - goto exit_remove; - - if (sio_data->kind == nct6776) { - err = device_create_file(dev, &sda_caseopen[1].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: - w83627ehf_device_remove_files(dev); -exit_release: - platform_set_drvdata(pdev, NULL); - release_region(res->start, IOREGION_LENGTH); -exit: - return err; -} - -static int __devexit w83627ehf_remove(struct platform_device *pdev) -{ - struct w83627ehf_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - w83627ehf_device_remove_files(&pdev->dev); - release_region(data->addr, IOREGION_LENGTH); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver w83627ehf_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = w83627ehf_probe, - .remove = __devexit_p(w83627ehf_remove), -}; - -/* w83627ehf_find() looks for a '627 in the Super-I/O config space */ -static int __init w83627ehf_find(int sioaddr, unsigned short *addr, - struct w83627ehf_sio_data *sio_data) -{ - static const char sio_name_W83627EHF[] __initconst = "W83627EHF"; - static const char sio_name_W83627EHG[] __initconst = "W83627EHG"; - static const char sio_name_W83627DHG[] __initconst = "W83627DHG"; - static const char sio_name_W83627DHG_P[] __initconst = "W83627DHG-P"; - static const char sio_name_W83627UHG[] __initconst = "W83627UHG"; - static const char sio_name_W83667HG[] __initconst = "W83667HG"; - static const char sio_name_W83667HG_B[] __initconst = "W83667HG-B"; - static const char sio_name_NCT6775[] __initconst = "NCT6775F"; - static const char sio_name_NCT6776[] __initconst = "NCT6776F"; - - 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_W83627EHF_ID: - sio_data->kind = w83627ehf; - sio_name = sio_name_W83627EHF; - break; - case SIO_W83627EHG_ID: - sio_data->kind = w83627ehf; - sio_name = sio_name_W83627EHG; - break; - case SIO_W83627DHG_ID: - sio_data->kind = w83627dhg; - sio_name = sio_name_W83627DHG; - break; - case SIO_W83627DHG_P_ID: - sio_data->kind = w83627dhg_p; - sio_name = sio_name_W83627DHG_P; - break; - case SIO_W83627UHG_ID: - sio_data->kind = w83627uhg; - sio_name = sio_name_W83627UHG; - break; - case SIO_W83667HG_ID: - sio_data->kind = w83667hg; - sio_name = sio_name_W83667HG; - break; - case SIO_W83667HG_B_ID: - sio_data->kind = w83667hg_b; - sio_name = sio_name_W83667HG_B; - break; - 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; - 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, W83627EHF_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 w83627ehf driver. But since we platform_device_alloc(), we - * must keep track of the device - */ -static struct platform_device *pdev; - -static int __init sensors_w83627ehf_init(void) -{ - int err; - unsigned short address; - struct resource res; - struct w83627ehf_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 - * w83627ehf hardware monitor, and call probe() - */ - if (w83627ehf_find(0x2e, &address, &sio_data) && - w83627ehf_find(0x4e, &address, &sio_data)) - return -ENODEV; - - err = platform_driver_register(&w83627ehf_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 w83627ehf_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(&w83627ehf_driver); -exit: - return err; -} - -static void __exit sensors_w83627ehf_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&w83627ehf_driver); -} - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("W83627EHF driver"); -MODULE_LICENSE("GPL"); - -module_init(sensors_w83627ehf_init); -module_exit(sensors_w83627ehf_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83627hf.c b/ANDROID_3.4.5/drivers/hwmon/w83627hf.c deleted file mode 100644 index 5ce54a29..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83627hf.c +++ /dev/null @@ -1,1948 +0,0 @@ -/* - * w83627hf.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998 - 2003 Frodo Looijaard , - * Philip Edelbrock , - * and Mark Studebaker - * Ported to 2.6 by Bernhard C. Schrenk - * Copyright (c) 2007 Jean Delvare - * - * 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 following chips: - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * w83627hf 9 3 2 3 0x20 0x5ca3 no yes(LPC) - * w83627thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) - * w83637hf 7 3 3 3 0x80 0x5ca3 no yes(LPC) - * w83687thf 7 3 3 3 0x90 0x5ca3 no yes(LPC) - * w83697hf 8 2 2 2 0x60 0x5ca3 no yes(LPC) - * - * For other winbond chips, and for i2c support in the above chips, - * use w83781d.c. - * - * Note: automatic ("cruise") fan control for 697, 637 & 627thf not - * supported yet. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "lm75.h" - -static struct platform_device *pdev; - -#define DRVNAME "w83627hf" -enum chips { w83627hf, w83627thf, w83697hf, w83637hf, w83687thf }; - -struct w83627hf_sio_data { - enum chips type; - int sioaddr; -}; - -static u8 force_i2c = 0x1f; -module_param(force_i2c, byte, 0); -MODULE_PARM_DESC(force_i2c, - "Initialize the i2c address of the sensors"); - -static bool init = 1; -module_param(init, bool, 0); -MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); - -static unsigned short force_id; -module_param(force_id, ushort, 0); -MODULE_PARM_DESC(force_id, "Override the detected device ID"); - -/* modified from kernel/include/traps.c */ -#define DEV 0x07 /* Register: Logical device select */ - -/* logical device numbers for superio_select (below) */ -#define W83627HF_LD_FDC 0x00 -#define W83627HF_LD_PRT 0x01 -#define W83627HF_LD_UART1 0x02 -#define W83627HF_LD_UART2 0x03 -#define W83627HF_LD_KBC 0x05 -#define W83627HF_LD_CIR 0x06 /* w83627hf only */ -#define W83627HF_LD_GAME 0x07 -#define W83627HF_LD_MIDI 0x07 -#define W83627HF_LD_GPIO1 0x07 -#define W83627HF_LD_GPIO5 0x07 /* w83627thf only */ -#define W83627HF_LD_GPIO2 0x08 -#define W83627HF_LD_GPIO3 0x09 -#define W83627HF_LD_GPIO4 0x09 /* w83627thf only */ -#define W83627HF_LD_ACPI 0x0a -#define W83627HF_LD_HWM 0x0b - -#define DEVID 0x20 /* Register: Device ID */ - -#define W83627THF_GPIO5_EN 0x30 /* w83627thf only */ -#define W83627THF_GPIO5_IOSR 0xf3 /* w83627thf only */ -#define W83627THF_GPIO5_DR 0xf4 /* w83627thf only */ - -#define W83687THF_VID_EN 0x29 /* w83687thf only */ -#define W83687THF_VID_CFG 0xF0 /* w83687thf only */ -#define W83687THF_VID_DATA 0xF1 /* w83687thf only */ - -static inline void -superio_outb(struct w83627hf_sio_data *sio, int reg, int val) -{ - outb(reg, sio->sioaddr); - outb(val, sio->sioaddr + 1); -} - -static inline int -superio_inb(struct w83627hf_sio_data *sio, int reg) -{ - outb(reg, sio->sioaddr); - return inb(sio->sioaddr + 1); -} - -static inline void -superio_select(struct w83627hf_sio_data *sio, int ld) -{ - outb(DEV, sio->sioaddr); - outb(ld, sio->sioaddr + 1); -} - -static inline void -superio_enter(struct w83627hf_sio_data *sio) -{ - outb(0x87, sio->sioaddr); - outb(0x87, sio->sioaddr); -} - -static inline void -superio_exit(struct w83627hf_sio_data *sio) -{ - outb(0xAA, sio->sioaddr); -} - -#define W627_DEVID 0x52 -#define W627THF_DEVID 0x82 -#define W697_DEVID 0x60 -#define W637_DEVID 0x70 -#define W687THF_DEVID 0x85 -#define WINB_ACT_REG 0x30 -#define WINB_BASE_REG 0x60 -/* Constants specified below */ - -/* Alignment of the base address */ -#define WINB_ALIGNMENT ~7 - -/* Offset & size of I/O region we are interested in */ -#define WINB_REGION_OFFSET 5 -#define WINB_REGION_SIZE 2 - -/* Where are the sensors address/data registers relative to the region offset */ -#define W83781D_ADDR_REG_OFFSET 0 -#define W83781D_DATA_REG_OFFSET 1 - -/* The W83781D registers */ -/* The W83782D registers for nr=7,8 are in bank 5 */ -#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ - (0x554 + (((nr) - 7) * 2))) -#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ - (0x555 + (((nr) - 7) * 2))) -#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ - (0x550 + (nr) - 7)) - -/* nr:0-2 for fans:1-3 */ -#define W83627HF_REG_FAN_MIN(nr) (0x3b + (nr)) -#define W83627HF_REG_FAN(nr) (0x28 + (nr)) - -#define W83627HF_REG_TEMP2_CONFIG 0x152 -#define W83627HF_REG_TEMP3_CONFIG 0x252 -/* these are zero-based, unlike config constants above */ -static const u16 w83627hf_reg_temp[] = { 0x27, 0x150, 0x250 }; -static const u16 w83627hf_reg_temp_hyst[] = { 0x3A, 0x153, 0x253 }; -static const u16 w83627hf_reg_temp_over[] = { 0x39, 0x155, 0x255 }; - -#define W83781D_REG_BANK 0x4E - -#define W83781D_REG_CONFIG 0x40 -#define W83781D_REG_ALARM1 0x459 -#define W83781D_REG_ALARM2 0x45A -#define W83781D_REG_ALARM3 0x45B - -#define W83781D_REG_BEEP_CONFIG 0x4D -#define W83781D_REG_BEEP_INTS1 0x56 -#define W83781D_REG_BEEP_INTS2 0x57 -#define W83781D_REG_BEEP_INTS3 0x453 - -#define W83781D_REG_VID_FANDIV 0x47 - -#define W83781D_REG_CHIPID 0x49 -#define W83781D_REG_WCHIPID 0x58 -#define W83781D_REG_CHIPMAN 0x4F -#define W83781D_REG_PIN 0x4B - -#define W83781D_REG_VBAT 0x5D - -#define W83627HF_REG_PWM1 0x5A -#define W83627HF_REG_PWM2 0x5B - -static const u8 W83627THF_REG_PWM_ENABLE[] = { - 0x04, /* FAN 1 mode */ - 0x04, /* FAN 2 mode */ - 0x12, /* FAN AUX mode */ -}; -static const u8 W83627THF_PWM_ENABLE_SHIFT[] = { 2, 4, 1 }; - -#define W83627THF_REG_PWM1 0x01 /* 697HF/637HF/687THF too */ -#define W83627THF_REG_PWM2 0x03 /* 697HF/637HF/687THF too */ -#define W83627THF_REG_PWM3 0x11 /* 637HF/687THF too */ - -#define W83627THF_REG_VRM_OVT_CFG 0x18 /* 637HF/687THF too */ - -static const u8 regpwm_627hf[] = { W83627HF_REG_PWM1, W83627HF_REG_PWM2 }; -static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2, - W83627THF_REG_PWM3 }; -#define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \ - regpwm_627hf[nr] : regpwm[nr]) - -#define W83627HF_REG_PWM_FREQ 0x5C /* Only for the 627HF */ - -#define W83637HF_REG_PWM_FREQ1 0x00 /* 697HF/687THF too */ -#define W83637HF_REG_PWM_FREQ2 0x02 /* 697HF/687THF too */ -#define W83637HF_REG_PWM_FREQ3 0x10 /* 687THF too */ - -static const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1, - W83637HF_REG_PWM_FREQ2, - W83637HF_REG_PWM_FREQ3 }; - -#define W83627HF_BASE_PWM_FREQ 46870 - -#define W83781D_REG_I2C_ADDR 0x48 -#define W83781D_REG_I2C_SUBADDR 0x4A - -/* Sensor selection */ -#define W83781D_REG_SCFG1 0x5D -static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 }; -#define W83781D_REG_SCFG2 0x59 -static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; -#define W83781D_DEFAULT_BETA 3435 - -/* - * Conversions. Limit checking is only done on the TO_REG - * variants. Note that you should be a bit careful with which arguments - * these macros are called: arguments may be evaluated more than once. - * Fixing this is just not worth it. - */ -#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8)/16),0,255)) -#define IN_FROM_REG(val) ((val) * 16) - -static inline u8 FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, - 254); -} - -#define TEMP_MIN (-128000) -#define TEMP_MAX ( 127000) - -/* - * TEMP: 0.001C/bit (-128C to +127C) - * REG: 1C/bit, two's complement - */ -static u8 TEMP_TO_REG(long temp) -{ - int ntemp = SENSORS_LIMIT(temp, TEMP_MIN, TEMP_MAX); - ntemp += (ntemp<0 ? -500 : 500); - return (u8)(ntemp / 1000); -} - -static int TEMP_FROM_REG(u8 reg) -{ - return (s8)reg * 1000; -} - -#define FAN_FROM_REG(val,div) ((val)==0?-1:(val)==255?0:1350000/((val)*(div))) - -#define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255)) - -static inline unsigned long pwm_freq_from_reg_627hf(u8 reg) -{ - unsigned long freq; - freq = W83627HF_BASE_PWM_FREQ >> reg; - return freq; -} -static inline u8 pwm_freq_to_reg_627hf(unsigned long val) -{ - u8 i; - /* - * Only 5 dividers (1 2 4 8 16) - * Search for the nearest available frequency - */ - for (i = 0; i < 4; i++) { - if (val > (((W83627HF_BASE_PWM_FREQ >> i) + - (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2)) - break; - } - return i; -} - -static inline unsigned long pwm_freq_from_reg(u8 reg) -{ - /* Clock bit 8 -> 180 kHz or 24 MHz */ - unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL; - - reg &= 0x7f; - /* This should not happen but anyway... */ - if (reg == 0) - reg++; - return clock / (reg << 8); -} -static inline u8 pwm_freq_to_reg(unsigned long val) -{ - /* Minimum divider value is 0x01 and maximum is 0x7F */ - if (val >= 93750) /* The highest we can do */ - return 0x01; - if (val >= 720) /* Use 24 MHz clock */ - return 24000000UL / (val << 8); - if (val < 6) /* The lowest we can do */ - return 0xFF; - else /* Use 180 kHz clock */ - return 0x80 | (180000UL / (val << 8)); -} - -#define BEEP_MASK_FROM_REG(val) ((val) & 0xff7fff) -#define BEEP_MASK_TO_REG(val) ((val) & 0xff7fff) - -#define DIV_FROM_REG(val) (1 << (val)) - -static inline u8 DIV_TO_REG(long val) -{ - int i; - val = SENSORS_LIMIT(val, 1, 128) >> 1; - for (i = 0; i < 7; i++) { - if (val == 0) - break; - val >>= 1; - } - return (u8)i; -} - -/* - * For each registered chip, we need to keep some data in memory. - * The structure is dynamically allocated. - */ -struct w83627hf_data { - unsigned short addr; - const char *name; - struct device *hwmon_dev; - struct mutex lock; - enum chips type; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - u8 in[9]; /* Register value */ - u8 in_max[9]; /* Register value */ - u8 in_min[9]; /* Register value */ - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - u16 temp[3]; /* Register value */ - u16 temp_max[3]; /* Register value */ - u16 temp_max_hyst[3]; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 vid; /* Register encoding, combined */ - u32 alarms; /* Register encoding, combined */ - u32 beep_mask; /* Register encoding, combined */ - u8 pwm[3]; /* Register value */ - u8 pwm_enable[3]; /* 1 = manual - * 2 = thermal cruise (also called SmartFan I) - * 3 = fan speed cruise - */ - u8 pwm_freq[3]; /* Register value */ - u16 sens[3]; /* 1 = pentium diode; 2 = 3904 diode; - * 4 = thermistor - */ - u8 vrm; - u8 vrm_ovt; /* Register value, 627THF/637HF/687THF only */ -}; - - -static int w83627hf_probe(struct platform_device *pdev); -static int __devexit w83627hf_remove(struct platform_device *pdev); - -static int w83627hf_read_value(struct w83627hf_data *data, u16 reg); -static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value); -static void w83627hf_update_fan_div(struct w83627hf_data *data); -static struct w83627hf_data *w83627hf_update_device(struct device *dev); -static void w83627hf_init_device(struct platform_device *pdev); - -static struct platform_driver w83627hf_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .probe = w83627hf_probe, - .remove = __devexit_p(w83627hf_remove), -}; - -static ssize_t -show_in_input(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in[nr])); -} -static ssize_t -show_in_min(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_min[nr])); -} -static ssize_t -show_in_max(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long)IN_FROM_REG(data->in_max[nr])); -} -static ssize_t -store_in_min(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_min[nr] = IN_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_IN_MIN(nr), data->in_min[nr]); - mutex_unlock(&data->update_lock); - return count; -} -static ssize_t -store_in_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->in_max[nr] = IN_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_IN_MAX(nr), data->in_max[nr]); - mutex_unlock(&data->update_lock); - return count; -} -#define sysfs_vin_decl(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in_input, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO|S_IWUSR, \ - show_in_min, store_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO|S_IWUSR, \ - show_in_max, store_in_max, offset); - -sysfs_vin_decl(1); -sysfs_vin_decl(2); -sysfs_vin_decl(3); -sysfs_vin_decl(4); -sysfs_vin_decl(5); -sysfs_vin_decl(6); -sysfs_vin_decl(7); -sysfs_vin_decl(8); - -/* use a different set of functions for in0 */ -static ssize_t show_in_0(struct w83627hf_data *data, char *buf, u8 reg) -{ - long in0; - - if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type - || w83687thf == data->type)) - - /* use VRM9 calculation */ - in0 = (long)((reg * 488 + 70000 + 50) / 100); - else - /* use VRM8 (standard) calculation */ - in0 = (long)IN_FROM_REG(reg); - - return sprintf(buf,"%ld\n", in0); -} - -static ssize_t show_regs_in_0(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - return show_in_0(data, buf, data->in[0]); -} - -static ssize_t show_regs_in_min0(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - return show_in_0(data, buf, data->in_min[0]); -} - -static ssize_t show_regs_in_max0(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - return show_in_0(data, buf, data->in_max[0]); -} - -static ssize_t store_regs_in_min0(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type - || w83687thf == data->type)) - - /* use VRM9 calculation */ - data->in_min[0] = - SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0, - 255); - else - /* use VRM8 (standard) calculation */ - data->in_min[0] = IN_TO_REG(val); - - w83627hf_write_value(data, W83781D_REG_IN_MIN(0), data->in_min[0]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t store_regs_in_max0(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - if ((data->vrm_ovt & 0x01) && - (w83627thf == data->type || w83637hf == data->type - || w83687thf == data->type)) - - /* use VRM9 calculation */ - data->in_max[0] = - SENSORS_LIMIT(((val * 100) - 70000 + 244) / 488, 0, - 255); - else - /* use VRM8 (standard) calculation */ - data->in_max[0] = IN_TO_REG(val); - - w83627hf_write_value(data, W83781D_REG_IN_MAX(0), data->in_max[0]); - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(in0_input, S_IRUGO, show_regs_in_0, NULL); -static DEVICE_ATTR(in0_min, S_IRUGO | S_IWUSR, - show_regs_in_min0, store_regs_in_min0); -static DEVICE_ATTR(in0_max, S_IRUGO | S_IWUSR, - show_regs_in_max0, store_regs_in_max0); - -static ssize_t -show_fan_input(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan[nr], - (long)DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t -show_fan_min(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", FAN_FROM_REG(data->fan_min[nr], - (long)DIV_FROM_REG(data->fan_div[nr]))); -} -static ssize_t -store_fan_min(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), - data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - return count; -} -#define sysfs_fan_decl(offset) \ -static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \ - show_fan_input, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, \ - show_fan_min, store_fan_min, offset - 1); - -sysfs_fan_decl(1); -sysfs_fan_decl(2); -sysfs_fan_decl(3); - -static ssize_t -show_temp(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - - u16 tmp = data->temp[nr]; - return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) - : (long) TEMP_FROM_REG(tmp)); -} - -static ssize_t -show_temp_max(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - - u16 tmp = data->temp_max[nr]; - return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) - : (long) TEMP_FROM_REG(tmp)); -} - -static ssize_t -show_temp_max_hyst(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - - u16 tmp = data->temp_max_hyst[nr]; - return sprintf(buf, "%ld\n", (nr) ? (long) LM75_TEMP_FROM_REG(tmp) - : (long) TEMP_FROM_REG(tmp)); -} - -static ssize_t -store_temp_max(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - u16 tmp; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); - mutex_lock(&data->update_lock); - data->temp_max[nr] = tmp; - w83627hf_write_value(data, w83627hf_reg_temp_over[nr], tmp); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_temp_max_hyst(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - u16 tmp; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - tmp = (nr) ? LM75_TEMP_TO_REG(val) : TEMP_TO_REG(val); - mutex_lock(&data->update_lock); - data->temp_max_hyst[nr] = tmp; - w83627hf_write_value(data, w83627hf_reg_temp_hyst[nr], tmp); - mutex_unlock(&data->update_lock); - return count; -} - -#define sysfs_temp_decl(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO|S_IWUSR, \ - show_temp_max, store_temp_max, offset - 1); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO|S_IWUSR, \ - show_temp_max_hyst, store_temp_max_hyst, offset - 1); - -sysfs_temp_decl(1); -sysfs_temp_decl(2); -sysfs_temp_decl(3); - -static ssize_t -show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); -} -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); - -static ssize_t -show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%ld\n", (long) data->vrm); -} -static ssize_t -store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - data->vrm = val; - - return count; -} -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); - -static ssize_t -show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long) data->alarms); -} -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); - -static ssize_t -show_alarm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16); -static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13); - -static ssize_t -show_beep_mask(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", - (long)BEEP_MASK_FROM_REG(data->beep_mask)); -} - -static ssize_t -store_beep_mask(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - /* preserve beep enable */ - data->beep_mask = (data->beep_mask & 0x8000) - | BEEP_MASK_TO_REG(val); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, - data->beep_mask & 0xff); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, - ((data->beep_mask) >> 16) & 0xff); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, - (data->beep_mask >> 8) & 0xff); - - mutex_unlock(&data->update_lock); - return count; -} - -static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, - show_beep_mask, store_beep_mask); - -static ssize_t -show_beep(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83627hf_data *data = w83627hf_update_device(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); -} - -static ssize_t -store_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - u8 reg; - unsigned long bit; - int err; - - err = kstrtoul(buf, 10, &bit); - if (err) - return err; - - if (bit & ~1) - return -EINVAL; - - mutex_lock(&data->update_lock); - if (bit) - data->beep_mask |= (1 << bitnr); - else - data->beep_mask &= ~(1 << bitnr); - - if (bitnr < 8) { - reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS1); - if (bit) - reg |= (1 << bitnr); - else - reg &= ~(1 << bitnr); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS1, reg); - } else if (bitnr < 16) { - reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); - if (bit) - reg |= (1 << (bitnr - 8)); - else - reg &= ~(1 << (bitnr - 8)); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS2, reg); - } else { - reg = w83627hf_read_value(data, W83781D_REG_BEEP_INTS3); - if (bit) - reg |= (1 << (bitnr - 16)); - else - reg &= ~(1 << (bitnr - 16)); - w83627hf_write_value(data, W83781D_REG_BEEP_INTS3, reg); - } - mutex_unlock(&data->update_lock); - - return count; -} - -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 0); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 2); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 3); -static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 8); -static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 9); -static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 10); -static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 16); -static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 17); -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 6); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 7); -static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 11); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 4); -static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 5); -static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 13); -static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, - show_beep, store_beep, 15); - -static ssize_t -show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", - (long) DIV_FROM_REG(data->fan_div[nr])); -} -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t -store_fan_div(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long min; - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - /* Save fan_min */ - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - - data->fan_div[nr] = DIV_TO_REG(val); - - reg = (w83627hf_read_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV) - & (nr==0 ? 0xcf : 0x3f)) - | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6)); - w83627hf_write_value(data, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); - - reg = (w83627hf_read_value(data, W83781D_REG_VBAT) - & ~(1 << (5 + nr))) - | ((data->fan_div[nr] & 0x04) << (3 + nr)); - w83627hf_write_value(data, W83781D_REG_VBAT, reg); - - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83627hf_write_value(data, W83627HF_REG_FAN_MIN(nr), data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO|S_IWUSR, - show_fan_div, store_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO|S_IWUSR, - show_fan_div, store_fan_div, 1); -static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO|S_IWUSR, - show_fan_div, store_fan_div, 2); - -static ssize_t -show_pwm(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long) data->pwm[nr]); -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - if (data->type == w83627thf) { - /* bits 0-3 are reserved in 627THF */ - data->pwm[nr] = PWM_TO_REG(val) & 0xf0; - w83627hf_write_value(data, - W836X7HF_REG_PWM(data->type, nr), - data->pwm[nr] | - (w83627hf_read_value(data, - W836X7HF_REG_PWM(data->type, nr)) & 0x0f)); - } else { - data->pwm[nr] = PWM_TO_REG(val); - w83627hf_write_value(data, - W836X7HF_REG_PWM(data->type, nr), - data->pwm[nr]); - } - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO|S_IWUSR, show_pwm, store_pwm, 2); - -static ssize_t -show_pwm_enable(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%d\n", data->pwm_enable[nr]); -} - -static ssize_t -store_pwm_enable(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (!val || val > 3) /* modes 1, 2 and 3 are supported */ - return -EINVAL; - mutex_lock(&data->update_lock); - data->pwm_enable[nr] = val; - reg = w83627hf_read_value(data, W83627THF_REG_PWM_ENABLE[nr]); - reg &= ~(0x03 << W83627THF_PWM_ENABLE_SHIFT[nr]); - reg |= (val - 1) << W83627THF_PWM_ENABLE_SHIFT[nr]; - w83627hf_write_value(data, W83627THF_REG_PWM_ENABLE[nr], reg); - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 0); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 1); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IRUGO|S_IWUSR, show_pwm_enable, - store_pwm_enable, 2); - -static ssize_t -show_pwm_freq(struct device *dev, struct device_attribute *devattr, char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - if (data->type == w83627hf) - return sprintf(buf, "%ld\n", - pwm_freq_from_reg_627hf(data->pwm_freq[nr])); - else - return sprintf(buf, "%ld\n", - pwm_freq_from_reg(data->pwm_freq[nr])); -} - -static ssize_t -store_pwm_freq(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - static const u8 mask[]={0xF8, 0x8F}; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - if (data->type == w83627hf) { - data->pwm_freq[nr] = pwm_freq_to_reg_627hf(val); - w83627hf_write_value(data, W83627HF_REG_PWM_FREQ, - (data->pwm_freq[nr] << (nr*4)) | - (w83627hf_read_value(data, - W83627HF_REG_PWM_FREQ) & mask[nr])); - } else { - data->pwm_freq[nr] = pwm_freq_to_reg(val); - w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr], - data->pwm_freq[nr]); - } - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1_freq, S_IRUGO|S_IWUSR, - show_pwm_freq, store_pwm_freq, 0); -static SENSOR_DEVICE_ATTR(pwm2_freq, S_IRUGO|S_IWUSR, - show_pwm_freq, store_pwm_freq, 1); -static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO|S_IWUSR, - show_pwm_freq, store_pwm_freq, 2); - -static ssize_t -show_temp_type(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = w83627hf_update_device(dev); - return sprintf(buf, "%ld\n", (long) data->sens[nr]); -} - -static ssize_t -store_temp_type(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(devattr)->index; - struct w83627hf_data *data = dev_get_drvdata(dev); - unsigned long val; - u32 tmp; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - switch (val) { - case 1: /* PII/Celeron diode */ - tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); - w83627hf_write_value(data, W83781D_REG_SCFG1, - tmp | BIT_SCFG1[nr]); - tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); - w83627hf_write_value(data, W83781D_REG_SCFG2, - tmp | BIT_SCFG2[nr]); - data->sens[nr] = val; - break; - case 2: /* 3904 */ - tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); - w83627hf_write_value(data, W83781D_REG_SCFG1, - tmp | BIT_SCFG1[nr]); - tmp = w83627hf_read_value(data, W83781D_REG_SCFG2); - w83627hf_write_value(data, W83781D_REG_SCFG2, - tmp & ~BIT_SCFG2[nr]); - data->sens[nr] = val; - break; - case W83781D_DEFAULT_BETA: - dev_warn(dev, "Sensor type %d is deprecated, please use 4 " - "instead\n", W83781D_DEFAULT_BETA); - /* fall through */ - case 4: /* thermistor */ - tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); - w83627hf_write_value(data, W83781D_REG_SCFG1, - tmp & ~BIT_SCFG1[nr]); - data->sens[nr] = val; - break; - default: - dev_err(dev, - "Invalid sensor type %ld; must be 1, 2, or 4\n", - (long) val); - break; - } - - mutex_unlock(&data->update_lock); - return count; -} - -#define sysfs_temp_type(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO | S_IWUSR, \ - show_temp_type, store_temp_type, offset - 1); - -sysfs_temp_type(1); -sysfs_temp_type(2); -sysfs_temp_type(3); - -static ssize_t -show_name(struct device *dev, struct device_attribute *devattr, char *buf) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static int __init w83627hf_find(int sioaddr, unsigned short *addr, - struct w83627hf_sio_data *sio_data) -{ - int err = -ENODEV; - u16 val; - - static const __initdata char *names[] = { - "W83627HF", - "W83627THF", - "W83697HF", - "W83637HF", - "W83687THF", - }; - - sio_data->sioaddr = sioaddr; - superio_enter(sio_data); - val = force_id ? force_id : superio_inb(sio_data, DEVID); - switch (val) { - case W627_DEVID: - sio_data->type = w83627hf; - break; - case W627THF_DEVID: - sio_data->type = w83627thf; - break; - case W697_DEVID: - sio_data->type = w83697hf; - break; - case W637_DEVID: - sio_data->type = w83637hf; - break; - case W687THF_DEVID: - sio_data->type = w83687thf; - break; - case 0xff: /* No device at all */ - goto exit; - default: - pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%02x)\n", val); - goto exit; - } - - superio_select(sio_data, W83627HF_LD_HWM); - val = (superio_inb(sio_data, WINB_BASE_REG) << 8) | - superio_inb(sio_data, WINB_BASE_REG + 1); - *addr = val & WINB_ALIGNMENT; - if (*addr == 0) { - pr_warn("Base address not set, skipping\n"); - goto exit; - } - - val = superio_inb(sio_data, WINB_ACT_REG); - if (!(val & 0x01)) { - pr_warn("Enabling HWM logical device\n"); - superio_outb(sio_data, WINB_ACT_REG, val | 0x01); - } - - err = 0; - pr_info(DRVNAME ": Found %s chip at %#x\n", - names[sio_data->type], *addr); - - exit: - superio_exit(sio_data); - return err; -} - -#define VIN_UNIT_ATTRS(_X_) \ - &sensor_dev_attr_in##_X_##_input.dev_attr.attr, \ - &sensor_dev_attr_in##_X_##_min.dev_attr.attr, \ - &sensor_dev_attr_in##_X_##_max.dev_attr.attr, \ - &sensor_dev_attr_in##_X_##_alarm.dev_attr.attr, \ - &sensor_dev_attr_in##_X_##_beep.dev_attr.attr - -#define FAN_UNIT_ATTRS(_X_) \ - &sensor_dev_attr_fan##_X_##_input.dev_attr.attr, \ - &sensor_dev_attr_fan##_X_##_min.dev_attr.attr, \ - &sensor_dev_attr_fan##_X_##_div.dev_attr.attr, \ - &sensor_dev_attr_fan##_X_##_alarm.dev_attr.attr, \ - &sensor_dev_attr_fan##_X_##_beep.dev_attr.attr - -#define TEMP_UNIT_ATTRS(_X_) \ - &sensor_dev_attr_temp##_X_##_input.dev_attr.attr, \ - &sensor_dev_attr_temp##_X_##_max.dev_attr.attr, \ - &sensor_dev_attr_temp##_X_##_max_hyst.dev_attr.attr, \ - &sensor_dev_attr_temp##_X_##_type.dev_attr.attr, \ - &sensor_dev_attr_temp##_X_##_alarm.dev_attr.attr, \ - &sensor_dev_attr_temp##_X_##_beep.dev_attr.attr - -static struct attribute *w83627hf_attributes[] = { - &dev_attr_in0_input.attr, - &dev_attr_in0_min.attr, - &dev_attr_in0_max.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in0_beep.dev_attr.attr, - VIN_UNIT_ATTRS(2), - VIN_UNIT_ATTRS(3), - VIN_UNIT_ATTRS(4), - VIN_UNIT_ATTRS(7), - VIN_UNIT_ATTRS(8), - - FAN_UNIT_ATTRS(1), - FAN_UNIT_ATTRS(2), - - TEMP_UNIT_ATTRS(1), - TEMP_UNIT_ATTRS(2), - - &dev_attr_alarms.attr, - &sensor_dev_attr_beep_enable.dev_attr.attr, - &dev_attr_beep_mask.attr, - - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &dev_attr_name.attr, - NULL -}; - -static const struct attribute_group w83627hf_group = { - .attrs = w83627hf_attributes, -}; - -static struct attribute *w83627hf_attributes_opt[] = { - VIN_UNIT_ATTRS(1), - VIN_UNIT_ATTRS(5), - VIN_UNIT_ATTRS(6), - - FAN_UNIT_ATTRS(3), - TEMP_UNIT_ATTRS(3), - &sensor_dev_attr_pwm3.dev_attr.attr, - - &sensor_dev_attr_pwm1_freq.dev_attr.attr, - &sensor_dev_attr_pwm2_freq.dev_attr.attr, - &sensor_dev_attr_pwm3_freq.dev_attr.attr, - - &sensor_dev_attr_pwm1_enable.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - - NULL -}; - -static const struct attribute_group w83627hf_group_opt = { - .attrs = w83627hf_attributes_opt, -}; - -static int __devinit w83627hf_probe(struct platform_device *pdev) -{ - struct device *dev = &pdev->dev; - struct w83627hf_sio_data *sio_data = dev->platform_data; - struct w83627hf_data *data; - struct resource *res; - int err, i; - - static const char *names[] = { - "w83627hf", - "w83627thf", - "w83697hf", - "w83637hf", - "w83687thf", - }; - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, WINB_REGION_SIZE, DRVNAME)) { - dev_err(dev, "Failed to request region 0x%lx-0x%lx\n", - (unsigned long)res->start, - (unsigned long)(res->start + WINB_REGION_SIZE - 1)); - err = -EBUSY; - goto ERROR0; - } - - data = kzalloc(sizeof(struct w83627hf_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto ERROR1; - } - data->addr = res->start; - data->type = sio_data->type; - data->name = names[sio_data->type]; - mutex_init(&data->lock); - mutex_init(&data->update_lock); - platform_set_drvdata(pdev, data); - - /* Initialize the chip */ - w83627hf_init_device(pdev); - - /* A few vars need to be filled upon startup */ - for (i = 0; i <= 2; i++) - data->fan_min[i] = w83627hf_read_value( - data, W83627HF_REG_FAN_MIN(i)); - w83627hf_update_fan_div(data); - - /* Register common device attributes */ - err = sysfs_create_group(&dev->kobj, &w83627hf_group); - if (err) - goto ERROR3; - - /* Register chip-specific device attributes */ - if (data->type == w83627hf || data->type == w83697hf) - if ((err = device_create_file(dev, - &sensor_dev_attr_in5_input.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in5_min.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in5_max.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in5_alarm.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in5_beep.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in6_input.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in6_min.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in6_max.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in6_alarm.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in6_beep.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm1_freq.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm2_freq.dev_attr))) - goto ERROR4; - - if (data->type != w83697hf) - if ((err = device_create_file(dev, - &sensor_dev_attr_in1_input.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in1_min.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in1_max.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in1_alarm.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_in1_beep.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_fan3_input.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_fan3_min.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_fan3_div.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_fan3_alarm.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_fan3_beep.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_temp3_input.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_temp3_max.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_temp3_max_hyst.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_temp3_alarm.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_temp3_beep.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_temp3_type.dev_attr))) - goto ERROR4; - - if (data->type != w83697hf && data->vid != 0xff) { - /* Convert VID to voltage based on VRM */ - data->vrm = vid_which_vrm(); - - if ((err = device_create_file(dev, &dev_attr_cpu0_vid)) - || (err = device_create_file(dev, &dev_attr_vrm))) - goto ERROR4; - } - - if (data->type == w83627thf || data->type == w83637hf - || data->type == w83687thf) { - err = device_create_file(dev, &sensor_dev_attr_pwm3.dev_attr); - if (err) - goto ERROR4; - } - - if (data->type == w83637hf || data->type == w83687thf) - if ((err = device_create_file(dev, - &sensor_dev_attr_pwm1_freq.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm2_freq.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm3_freq.dev_attr))) - goto ERROR4; - - if (data->type != w83627hf) - if ((err = device_create_file(dev, - &sensor_dev_attr_pwm1_enable.dev_attr)) - || (err = device_create_file(dev, - &sensor_dev_attr_pwm2_enable.dev_attr))) - goto ERROR4; - - if (data->type == w83627thf || data->type == w83637hf - || data->type == w83687thf) { - err = device_create_file(dev, - &sensor_dev_attr_pwm3_enable.dev_attr); - if (err) - goto ERROR4; - } - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto ERROR4; - } - - return 0; - - ERROR4: - sysfs_remove_group(&dev->kobj, &w83627hf_group); - sysfs_remove_group(&dev->kobj, &w83627hf_group_opt); - ERROR3: - platform_set_drvdata(pdev, NULL); - kfree(data); - ERROR1: - release_region(res->start, WINB_REGION_SIZE); - ERROR0: - return err; -} - -static int __devexit w83627hf_remove(struct platform_device *pdev) -{ - struct w83627hf_data *data = platform_get_drvdata(pdev); - struct resource *res; - - hwmon_device_unregister(data->hwmon_dev); - - sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group); - sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt); - platform_set_drvdata(pdev, NULL); - kfree(data); - - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - release_region(res->start, WINB_REGION_SIZE); - - return 0; -} - - -/* Registers 0x50-0x5f are banked */ -static inline void w83627hf_set_bank(struct w83627hf_data *data, u16 reg) -{ - if ((reg & 0x00f0) == 0x50) { - outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8, data->addr + W83781D_DATA_REG_OFFSET); - } -} - -/* Not strictly necessary, but play it safe for now */ -static inline void w83627hf_reset_bank(struct w83627hf_data *data, u16 reg) -{ - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, data->addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, data->addr + W83781D_DATA_REG_OFFSET); - } -} - -static int w83627hf_read_value(struct w83627hf_data *data, u16 reg) -{ - int res, word_sized; - - mutex_lock(&data->lock); - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) - && (((reg & 0x00ff) == 0x50) - || ((reg & 0x00ff) == 0x53) - || ((reg & 0x00ff) == 0x55)); - w83627hf_set_bank(data, reg); - outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); - res = inb_p(data->addr + W83781D_DATA_REG_OFFSET); - if (word_sized) { - outb_p((reg & 0xff) + 1, - data->addr + W83781D_ADDR_REG_OFFSET); - res = - (res << 8) + inb_p(data->addr + - W83781D_DATA_REG_OFFSET); - } - w83627hf_reset_bank(data, reg); - mutex_unlock(&data->lock); - return res; -} - -static int __devinit w83627thf_read_gpio5(struct platform_device *pdev) -{ - struct w83627hf_sio_data *sio_data = pdev->dev.platform_data; - int res = 0xff, sel; - - superio_enter(sio_data); - superio_select(sio_data, W83627HF_LD_GPIO5); - - /* Make sure these GPIO pins are enabled */ - if (!(superio_inb(sio_data, W83627THF_GPIO5_EN) & (1<<3))) { - dev_dbg(&pdev->dev, "GPIO5 disabled, no VID function\n"); - goto exit; - } - - /* - * Make sure the pins are configured for input - * There must be at least five (VRM 9), and possibly 6 (VRM 10) - */ - sel = superio_inb(sio_data, W83627THF_GPIO5_IOSR) & 0x3f; - if ((sel & 0x1f) != 0x1f) { - dev_dbg(&pdev->dev, "GPIO5 not configured for VID " - "function\n"); - goto exit; - } - - dev_info(&pdev->dev, "Reading VID from GPIO5\n"); - res = superio_inb(sio_data, W83627THF_GPIO5_DR) & sel; - -exit: - superio_exit(sio_data); - return res; -} - -static int __devinit w83687thf_read_vid(struct platform_device *pdev) -{ - struct w83627hf_sio_data *sio_data = pdev->dev.platform_data; - int res = 0xff; - - superio_enter(sio_data); - superio_select(sio_data, W83627HF_LD_HWM); - - /* Make sure these GPIO pins are enabled */ - if (!(superio_inb(sio_data, W83687THF_VID_EN) & (1 << 2))) { - dev_dbg(&pdev->dev, "VID disabled, no VID function\n"); - goto exit; - } - - /* Make sure the pins are configured for input */ - if (!(superio_inb(sio_data, W83687THF_VID_CFG) & (1 << 4))) { - dev_dbg(&pdev->dev, "VID configured as output, " - "no VID function\n"); - goto exit; - } - - res = superio_inb(sio_data, W83687THF_VID_DATA) & 0x3f; - -exit: - superio_exit(sio_data); - return res; -} - -static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value) -{ - int word_sized; - - mutex_lock(&data->lock); - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) - && (((reg & 0x00ff) == 0x53) - || ((reg & 0x00ff) == 0x55)); - w83627hf_set_bank(data, reg); - outb_p(reg & 0xff, data->addr + W83781D_ADDR_REG_OFFSET); - if (word_sized) { - outb_p(value >> 8, - data->addr + W83781D_DATA_REG_OFFSET); - outb_p((reg & 0xff) + 1, - data->addr + W83781D_ADDR_REG_OFFSET); - } - outb_p(value & 0xff, - data->addr + W83781D_DATA_REG_OFFSET); - w83627hf_reset_bank(data, reg); - mutex_unlock(&data->lock); - return 0; -} - -static void __devinit w83627hf_init_device(struct platform_device *pdev) -{ - struct w83627hf_data *data = platform_get_drvdata(pdev); - int i; - enum chips type = data->type; - u8 tmp; - - /* Minimize conflicts with other winbond i2c-only clients... */ - /* disable i2c subclients... how to disable main i2c client?? */ - /* force i2c address to relatively uncommon address */ - w83627hf_write_value(data, W83781D_REG_I2C_SUBADDR, 0x89); - w83627hf_write_value(data, W83781D_REG_I2C_ADDR, force_i2c); - - /* Read VID only once */ - if (type == w83627hf || type == w83637hf) { - int lo = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); - int hi = w83627hf_read_value(data, W83781D_REG_CHIPID); - data->vid = (lo & 0x0f) | ((hi & 0x01) << 4); - } else if (type == w83627thf) { - data->vid = w83627thf_read_gpio5(pdev); - } else if (type == w83687thf) { - data->vid = w83687thf_read_vid(pdev); - } - - /* Read VRM & OVT Config only once */ - if (type == w83627thf || type == w83637hf || type == w83687thf) { - data->vrm_ovt = - w83627hf_read_value(data, W83627THF_REG_VRM_OVT_CFG); - } - - tmp = w83627hf_read_value(data, W83781D_REG_SCFG1); - for (i = 1; i <= 3; i++) { - if (!(tmp & BIT_SCFG1[i - 1])) { - data->sens[i - 1] = 4; - } else { - if (w83627hf_read_value - (data, - W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) - data->sens[i - 1] = 1; - else - data->sens[i - 1] = 2; - } - if ((type == w83697hf) && (i == 2)) - break; - } - - if(init) { - /* Enable temp2 */ - tmp = w83627hf_read_value(data, W83627HF_REG_TEMP2_CONFIG); - if (tmp & 0x01) { - dev_warn(&pdev->dev, "Enabling temp2, readings " - "might not make sense\n"); - w83627hf_write_value(data, W83627HF_REG_TEMP2_CONFIG, - tmp & 0xfe); - } - - /* Enable temp3 */ - if (type != w83697hf) { - tmp = w83627hf_read_value(data, - W83627HF_REG_TEMP3_CONFIG); - if (tmp & 0x01) { - dev_warn(&pdev->dev, "Enabling temp3, " - "readings might not make sense\n"); - w83627hf_write_value(data, - W83627HF_REG_TEMP3_CONFIG, tmp & 0xfe); - } - } - } - - /* Start monitoring */ - w83627hf_write_value(data, W83781D_REG_CONFIG, - (w83627hf_read_value(data, - W83781D_REG_CONFIG) & 0xf7) - | 0x01); - - /* Enable VBAT monitoring if needed */ - tmp = w83627hf_read_value(data, W83781D_REG_VBAT); - if (!(tmp & 0x01)) - w83627hf_write_value(data, W83781D_REG_VBAT, tmp | 0x01); -} - -static void w83627hf_update_fan_div(struct w83627hf_data *data) -{ - int reg; - - reg = w83627hf_read_value(data, W83781D_REG_VID_FANDIV); - data->fan_div[0] = (reg >> 4) & 0x03; - data->fan_div[1] = (reg >> 6) & 0x03; - if (data->type != w83697hf) { - data->fan_div[2] = (w83627hf_read_value(data, - W83781D_REG_PIN) >> 6) & 0x03; - } - reg = w83627hf_read_value(data, W83781D_REG_VBAT); - data->fan_div[0] |= (reg >> 3) & 0x04; - data->fan_div[1] |= (reg >> 4) & 0x04; - if (data->type != w83697hf) - data->fan_div[2] |= (reg >> 5) & 0x04; -} - -static struct w83627hf_data *w83627hf_update_device(struct device *dev) -{ - struct w83627hf_data *data = dev_get_drvdata(dev); - int i, num_temps = (data->type == w83697hf) ? 2 : 3; - int num_pwms = (data->type == w83697hf) ? 2 : 3; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - for (i = 0; i <= 8; i++) { - /* skip missing sensors */ - if (((data->type == w83697hf) && (i == 1)) || - ((data->type != w83627hf && data->type != w83697hf) - && (i == 5 || i == 6))) - continue; - data->in[i] = - w83627hf_read_value(data, W83781D_REG_IN(i)); - data->in_min[i] = - w83627hf_read_value(data, - W83781D_REG_IN_MIN(i)); - data->in_max[i] = - w83627hf_read_value(data, - W83781D_REG_IN_MAX(i)); - } - for (i = 0; i <= 2; i++) { - data->fan[i] = - w83627hf_read_value(data, W83627HF_REG_FAN(i)); - data->fan_min[i] = - w83627hf_read_value(data, - W83627HF_REG_FAN_MIN(i)); - } - for (i = 0; i <= 2; i++) { - u8 tmp = w83627hf_read_value(data, - W836X7HF_REG_PWM(data->type, i)); - /* bits 0-3 are reserved in 627THF */ - if (data->type == w83627thf) - tmp &= 0xf0; - data->pwm[i] = tmp; - if (i == 1 && - (data->type == w83627hf || data->type == w83697hf)) - break; - } - if (data->type == w83627hf) { - u8 tmp = w83627hf_read_value(data, - W83627HF_REG_PWM_FREQ); - data->pwm_freq[0] = tmp & 0x07; - data->pwm_freq[1] = (tmp >> 4) & 0x07; - } else if (data->type != w83627thf) { - for (i = 1; i <= 3; i++) { - data->pwm_freq[i - 1] = - w83627hf_read_value(data, - W83637HF_REG_PWM_FREQ[i - 1]); - if (i == 2 && (data->type == w83697hf)) - break; - } - } - if (data->type != w83627hf) { - for (i = 0; i < num_pwms; i++) { - u8 tmp = w83627hf_read_value(data, - W83627THF_REG_PWM_ENABLE[i]); - data->pwm_enable[i] = - ((tmp >> W83627THF_PWM_ENABLE_SHIFT[i]) - & 0x03) + 1; - } - } - for (i = 0; i < num_temps; i++) { - data->temp[i] = w83627hf_read_value( - data, w83627hf_reg_temp[i]); - data->temp_max[i] = w83627hf_read_value( - data, w83627hf_reg_temp_over[i]); - data->temp_max_hyst[i] = w83627hf_read_value( - data, w83627hf_reg_temp_hyst[i]); - } - - w83627hf_update_fan_div(data); - - data->alarms = - w83627hf_read_value(data, W83781D_REG_ALARM1) | - (w83627hf_read_value(data, W83781D_REG_ALARM2) << 8) | - (w83627hf_read_value(data, W83781D_REG_ALARM3) << 16); - i = w83627hf_read_value(data, W83781D_REG_BEEP_INTS2); - data->beep_mask = (i << 8) | - w83627hf_read_value(data, W83781D_REG_BEEP_INTS1) | - w83627hf_read_value(data, W83781D_REG_BEEP_INTS3) << 16; - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static int __init w83627hf_device_add(unsigned short address, - const struct w83627hf_sio_data *sio_data) -{ - struct resource res = { - .start = address + WINB_REGION_OFFSET, - .end = address + WINB_REGION_OFFSET + WINB_REGION_SIZE - 1, - .name = DRVNAME, - .flags = IORESOURCE_IO, - }; - int err; - - err = acpi_check_resource_conflict(&res); - if (err) - goto exit; - - pdev = platform_device_alloc(DRVNAME, address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - err = platform_device_add_data(pdev, sio_data, - sizeof(struct w83627hf_sio_data)); - if (err) { - pr_err("Platform data allocation failed\n"); - goto exit_device_put; - } - - 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: - return err; -} - -static int __init sensors_w83627hf_init(void) -{ - int err; - unsigned short address; - struct w83627hf_sio_data sio_data; - - if (w83627hf_find(0x2e, &address, &sio_data) - && w83627hf_find(0x4e, &address, &sio_data)) - return -ENODEV; - - err = platform_driver_register(&w83627hf_driver); - if (err) - goto exit; - - /* Sets global pdev as a side effect */ - err = w83627hf_device_add(address, &sio_data); - if (err) - goto exit_driver; - - return 0; - -exit_driver: - platform_driver_unregister(&w83627hf_driver); -exit: - return err; -} - -static void __exit sensors_w83627hf_exit(void) -{ - platform_device_unregister(pdev); - platform_driver_unregister(&w83627hf_driver); -} - -MODULE_AUTHOR("Frodo Looijaard , " - "Philip Edelbrock , " - "and Mark Studebaker "); -MODULE_DESCRIPTION("W83627HF driver"); -MODULE_LICENSE("GPL"); - -module_init(sensors_w83627hf_init); -module_exit(sensors_w83627hf_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83781d.c b/ANDROID_3.4.5/drivers/hwmon/w83781d.c deleted file mode 100644 index b03d54a7..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83781d.c +++ /dev/null @@ -1,2118 +0,0 @@ -/* - * w83781d.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (c) 1998 - 2001 Frodo Looijaard , - * Philip Edelbrock , - * and Mark Studebaker - * Copyright (c) 2007 - 2008 Jean Delvare - * - * 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 following chips: - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * as99127f 7 3 0 3 0x31 0x12c3 yes no - * as99127f rev.2 (type_name = as99127f) 0x31 0x5ca3 yes no - * w83781d 7 3 0 3 0x10-1 0x5ca3 yes yes - * w83782d 9 3 2-4 3 0x30 0x5ca3 yes yes - * w83783s 5-6 3 2 1-2 0x40 0x5ca3 yes no - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_ISA -#include -#include -#include -#endif - -#include "lm75.h" - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, - 0x2e, 0x2f, I2C_CLIENT_END }; - -enum chips { w83781d, w83782d, w83783s, as99127f }; - -/* Insmod parameters */ -static unsigned short force_subclients[4]; -module_param_array(force_subclients, short, NULL, 0); -MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); - -static bool reset; -module_param(reset, bool, 0); -MODULE_PARM_DESC(reset, "Set to one to reset chip on load"); - -static bool init = 1; -module_param(init, bool, 0); -MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization"); - -/* Constants specified below */ - -/* Length of ISA address segment */ -#define W83781D_EXTENT 8 - -/* Where are the ISA address/data registers relative to the base address */ -#define W83781D_ADDR_REG_OFFSET 5 -#define W83781D_DATA_REG_OFFSET 6 - -/* The device registers */ -/* in nr from 0 to 8 */ -#define W83781D_REG_IN_MAX(nr) ((nr < 7) ? (0x2b + (nr) * 2) : \ - (0x554 + (((nr) - 7) * 2))) -#define W83781D_REG_IN_MIN(nr) ((nr < 7) ? (0x2c + (nr) * 2) : \ - (0x555 + (((nr) - 7) * 2))) -#define W83781D_REG_IN(nr) ((nr < 7) ? (0x20 + (nr)) : \ - (0x550 + (nr) - 7)) - -/* fan nr from 0 to 2 */ -#define W83781D_REG_FAN_MIN(nr) (0x3b + (nr)) -#define W83781D_REG_FAN(nr) (0x28 + (nr)) - -#define W83781D_REG_BANK 0x4E -#define W83781D_REG_TEMP2_CONFIG 0x152 -#define W83781D_REG_TEMP3_CONFIG 0x252 -/* temp nr from 1 to 3 */ -#define W83781D_REG_TEMP(nr) ((nr == 3) ? (0x0250) : \ - ((nr == 2) ? (0x0150) : \ - (0x27))) -#define W83781D_REG_TEMP_HYST(nr) ((nr == 3) ? (0x253) : \ - ((nr == 2) ? (0x153) : \ - (0x3A))) -#define W83781D_REG_TEMP_OVER(nr) ((nr == 3) ? (0x255) : \ - ((nr == 2) ? (0x155) : \ - (0x39))) - -#define W83781D_REG_CONFIG 0x40 - -/* Interrupt status (W83781D, AS99127F) */ -#define W83781D_REG_ALARM1 0x41 -#define W83781D_REG_ALARM2 0x42 - -/* Real-time status (W83782D, W83783S) */ -#define W83782D_REG_ALARM1 0x459 -#define W83782D_REG_ALARM2 0x45A -#define W83782D_REG_ALARM3 0x45B - -#define W83781D_REG_BEEP_CONFIG 0x4D -#define W83781D_REG_BEEP_INTS1 0x56 -#define W83781D_REG_BEEP_INTS2 0x57 -#define W83781D_REG_BEEP_INTS3 0x453 /* not on W83781D */ - -#define W83781D_REG_VID_FANDIV 0x47 - -#define W83781D_REG_CHIPID 0x49 -#define W83781D_REG_WCHIPID 0x58 -#define W83781D_REG_CHIPMAN 0x4F -#define W83781D_REG_PIN 0x4B - -/* 782D/783S only */ -#define W83781D_REG_VBAT 0x5D - -/* PWM 782D (1-4) and 783S (1-2) only */ -static const u8 W83781D_REG_PWM[] = { 0x5B, 0x5A, 0x5E, 0x5F }; -#define W83781D_REG_PWMCLK12 0x5C -#define W83781D_REG_PWMCLK34 0x45C - -#define W83781D_REG_I2C_ADDR 0x48 -#define W83781D_REG_I2C_SUBADDR 0x4A - -/* - * The following are undocumented in the data sheets however we - * received the information in an email from Winbond tech support - */ -/* Sensor selection - not on 781d */ -#define W83781D_REG_SCFG1 0x5D -static const u8 BIT_SCFG1[] = { 0x02, 0x04, 0x08 }; - -#define W83781D_REG_SCFG2 0x59 -static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 }; - -#define W83781D_DEFAULT_BETA 3435 - -/* Conversions */ -#define IN_TO_REG(val) SENSORS_LIMIT(((val) + 8) / 16, 0, 255) -#define IN_FROM_REG(val) ((val) * 16) - -static inline u8 -FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -static inline long -FAN_FROM_REG(u8 val, int div) -{ - if (val == 0) - return -1; - if (val == 255) - return 0; - return 1350000 / (val * div); -} - -#define TEMP_TO_REG(val) SENSORS_LIMIT((val) / 1000, -127, 128) -#define TEMP_FROM_REG(val) ((val) * 1000) - -#define BEEP_MASK_FROM_REG(val, type) ((type) == as99127f ? \ - (~(val)) & 0x7fff : (val) & 0xff7fff) -#define BEEP_MASK_TO_REG(val, type) ((type) == as99127f ? \ - (~(val)) & 0x7fff : (val) & 0xff7fff) - -#define DIV_FROM_REG(val) (1 << (val)) - -static inline u8 -DIV_TO_REG(long val, enum chips type) -{ - int i; - val = SENSORS_LIMIT(val, 1, - ((type == w83781d - || type == as99127f) ? 8 : 128)) >> 1; - for (i = 0; i < 7; i++) { - if (val == 0) - break; - val >>= 1; - } - return i; -} - -struct w83781d_data { - struct i2c_client *client; - struct device *hwmon_dev; - struct mutex lock; - enum chips type; - - /* For ISA device only */ - const char *name; - int isa_addr; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - struct i2c_client *lm75[2]; /* for secondary I2C addresses */ - /* array of 2 pointers to subclients */ - - u8 in[9]; /* Register value - 8 & 9 for 782D only */ - u8 in_max[9]; /* Register value - 8 & 9 for 782D only */ - u8 in_min[9]; /* Register value - 8 & 9 for 782D only */ - u8 fan[3]; /* Register value */ - u8 fan_min[3]; /* Register value */ - s8 temp; /* Register value */ - s8 temp_max; /* Register value */ - s8 temp_max_hyst; /* Register value */ - u16 temp_add[2]; /* Register value */ - u16 temp_max_add[2]; /* Register value */ - u16 temp_max_hyst_add[2]; /* Register value */ - u8 fan_div[3]; /* Register encoding, shifted right */ - u8 vid; /* Register encoding, combined */ - u32 alarms; /* Register encoding, combined */ - u32 beep_mask; /* Register encoding, combined */ - u8 pwm[4]; /* Register value */ - u8 pwm2_enable; /* Boolean */ - u16 sens[3]; /* - * 782D/783S only. - * 1 = pentium diode; 2 = 3904 diode; - * 4 = thermistor - */ - u8 vrm; -}; - -static struct w83781d_data *w83781d_data_if_isa(void); -static int w83781d_alias_detect(struct i2c_client *client, u8 chipid); - -static int w83781d_read_value(struct w83781d_data *data, u16 reg); -static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value); -static struct w83781d_data *w83781d_update_device(struct device *dev); -static void w83781d_init_device(struct device *dev); - -/* following are the sysfs callback functions */ -#define show_in_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \ - char *buf) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - struct w83781d_data *data = w83781d_update_device(dev); \ - return sprintf(buf, "%ld\n", \ - (long)IN_FROM_REG(data->reg[attr->index])); \ -} -show_in_reg(in); -show_in_reg(in_min); -show_in_reg(in_max); - -#define store_in_reg(REG, reg) \ -static ssize_t store_in_##reg(struct device *dev, struct device_attribute \ - *da, const char *buf, size_t count) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - struct w83781d_data *data = dev_get_drvdata(dev); \ - int nr = attr->index; \ - unsigned long val; \ - int err = kstrtoul(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - w83781d_write_value(data, W83781D_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ - \ - mutex_unlock(&data->update_lock); \ - return count; \ -} -store_in_reg(MIN, min); -store_in_reg(MAX, max); - -#define sysfs_in_offsets(offset) \ -static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \ - show_in, NULL, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \ - show_in_min, store_in_min, offset); \ -static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \ - show_in_max, store_in_max, offset) - -sysfs_in_offsets(0); -sysfs_in_offsets(1); -sysfs_in_offsets(2); -sysfs_in_offsets(3); -sysfs_in_offsets(4); -sysfs_in_offsets(5); -sysfs_in_offsets(6); -sysfs_in_offsets(7); -sysfs_in_offsets(8); - -#define show_fan_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \ - char *buf) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - struct w83781d_data *data = w83781d_update_device(dev); \ - return sprintf(buf, "%ld\n", \ - FAN_FROM_REG(data->reg[attr->index], \ - DIV_FROM_REG(data->fan_div[attr->index]))); \ -} -show_fan_reg(fan); -show_fan_reg(fan_min); - -static ssize_t -store_fan_min(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = - FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), - data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); -static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO | S_IWUSR, - show_fan_min, store_fan_min, 0); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO | S_IWUSR, - show_fan_min, store_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO | S_IWUSR, - show_fan_min, store_fan_min, 2); - -#define show_temp_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *da, \ - char *buf) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - struct w83781d_data *data = w83781d_update_device(dev); \ - int nr = attr->index; \ - if (nr >= 2) { /* TEMP2 and TEMP3 */ \ - return sprintf(buf, "%d\n", \ - LM75_TEMP_FROM_REG(data->reg##_add[nr-2])); \ - } else { /* TEMP1 */ \ - return sprintf(buf, "%ld\n", (long)TEMP_FROM_REG(data->reg)); \ - } \ -} -show_temp_reg(temp); -show_temp_reg(temp_max); -show_temp_reg(temp_max_hyst); - -#define store_temp_reg(REG, reg) \ -static ssize_t store_temp_##reg(struct device *dev, \ - struct device_attribute *da, const char *buf, size_t count) \ -{ \ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); \ - struct w83781d_data *data = dev_get_drvdata(dev); \ - int nr = attr->index; \ - long val; \ - int err = kstrtol(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - \ - if (nr >= 2) { /* TEMP2 and TEMP3 */ \ - data->temp_##reg##_add[nr-2] = LM75_TEMP_TO_REG(val); \ - w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ - data->temp_##reg##_add[nr-2]); \ - } else { /* TEMP1 */ \ - data->temp_##reg = TEMP_TO_REG(val); \ - w83781d_write_value(data, W83781D_REG_TEMP_##REG(nr), \ - data->temp_##reg); \ - } \ - \ - mutex_unlock(&data->update_lock); \ - return count; \ -} -store_temp_reg(OVER, max); -store_temp_reg(HYST, max_hyst); - -#define sysfs_temp_offsets(offset) \ -static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \ - show_temp, NULL, offset); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, \ - show_temp_max, store_temp_max, offset); \ -static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp_max_hyst, store_temp_max_hyst, offset); - -sysfs_temp_offsets(1); -sysfs_temp_offsets(2); -sysfs_temp_offsets(3); - -static ssize_t -show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%ld\n", (long) vid_from_reg(data->vid, data->vrm)); -} - -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); - -static ssize_t -show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%ld\n", (long) data->vrm); -} - -static ssize_t -store_vrm_reg(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - data->vrm = SENSORS_LIMIT(val, 0, 255); - - return count; -} - -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); - -static ssize_t -show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -/* The W83781D has a single alarm bit for temp2 and temp3 */ -static ssize_t show_temp3_alarm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - int bitnr = (data->type == w83781d) ? 5 : 13; - return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); -} - -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, 8); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 16); -static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 17); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_temp3_alarm, NULL, 0); - -static ssize_t show_beep_mask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%ld\n", - (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type)); -} - -static ssize_t -store_beep_mask(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->beep_mask &= 0x8000; /* preserve beep enable */ - data->beep_mask |= BEEP_MASK_TO_REG(val, data->type); - w83781d_write_value(data, W83781D_REG_BEEP_INTS1, - data->beep_mask & 0xff); - w83781d_write_value(data, W83781D_REG_BEEP_INTS2, - (data->beep_mask >> 8) & 0xff); - if (data->type != w83781d && data->type != as99127f) { - w83781d_write_value(data, W83781D_REG_BEEP_INTS3, - ((data->beep_mask) >> 16) & 0xff); - } - mutex_unlock(&data->update_lock); - - return count; -} - -static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR, - show_beep_mask, store_beep_mask); - -static ssize_t show_beep(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); -} - -static ssize_t -store_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - int bitnr = to_sensor_dev_attr(attr)->index; - u8 reg; - unsigned long bit; - int err; - - err = kstrtoul(buf, 10, &bit); - if (err) - return err; - - if (bit & ~1) - return -EINVAL; - - mutex_lock(&data->update_lock); - if (bit) - data->beep_mask |= (1 << bitnr); - else - data->beep_mask &= ~(1 << bitnr); - - if (bitnr < 8) { - reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS1); - if (bit) - reg |= (1 << bitnr); - else - reg &= ~(1 << bitnr); - w83781d_write_value(data, W83781D_REG_BEEP_INTS1, reg); - } else if (bitnr < 16) { - reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); - if (bit) - reg |= (1 << (bitnr - 8)); - else - reg &= ~(1 << (bitnr - 8)); - w83781d_write_value(data, W83781D_REG_BEEP_INTS2, reg); - } else { - reg = w83781d_read_value(data, W83781D_REG_BEEP_INTS3); - if (bit) - reg |= (1 << (bitnr - 16)); - else - reg &= ~(1 << (bitnr - 16)); - w83781d_write_value(data, W83781D_REG_BEEP_INTS3, reg); - } - mutex_unlock(&data->update_lock); - - return count; -} - -/* The W83781D has a single beep bit for temp2 and temp3 */ -static ssize_t show_temp3_beep(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - int bitnr = (data->type == w83781d) ? 5 : 13; - return sprintf(buf, "%u\n", (data->beep_mask >> bitnr) & 1); -} - -static SENSOR_DEVICE_ATTR(in0_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 0); -static SENSOR_DEVICE_ATTR(in1_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 1); -static SENSOR_DEVICE_ATTR(in2_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 2); -static SENSOR_DEVICE_ATTR(in3_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 3); -static SENSOR_DEVICE_ATTR(in4_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 8); -static SENSOR_DEVICE_ATTR(in5_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 9); -static SENSOR_DEVICE_ATTR(in6_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 10); -static SENSOR_DEVICE_ATTR(in7_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 16); -static SENSOR_DEVICE_ATTR(in8_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 17); -static SENSOR_DEVICE_ATTR(fan1_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 6); -static SENSOR_DEVICE_ATTR(fan2_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 7); -static SENSOR_DEVICE_ATTR(fan3_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 11); -static SENSOR_DEVICE_ATTR(temp1_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 4); -static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR, - show_beep, store_beep, 5); -static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO, - show_temp3_beep, store_beep, 13); -static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR, - show_beep, store_beep, 15); - -static ssize_t -show_fan_div(struct device *dev, struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%ld\n", - (long) DIV_FROM_REG(data->fan_div[attr->index])); -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t -store_fan_div(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = dev_get_drvdata(dev); - unsigned long min; - int nr = attr->index; - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - /* Save fan_min */ - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - - data->fan_div[nr] = DIV_TO_REG(val, data->type); - - reg = (w83781d_read_value(data, nr == 2 ? - W83781D_REG_PIN : W83781D_REG_VID_FANDIV) - & (nr == 0 ? 0xcf : 0x3f)) - | ((data->fan_div[nr] & 0x03) << (nr == 0 ? 4 : 6)); - w83781d_write_value(data, nr == 2 ? - W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg); - - /* w83781d and as99127f don't have extended divisor bits */ - if (data->type != w83781d && data->type != as99127f) { - reg = (w83781d_read_value(data, W83781D_REG_VBAT) - & ~(1 << (5 + nr))) - | ((data->fan_div[nr] & 0x04) << (3 + nr)); - w83781d_write_value(data, W83781D_REG_VBAT, reg); - } - - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83781d_write_value(data, W83781D_REG_FAN_MIN(nr), data->fan_min[nr]); - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, - show_fan_div, store_fan_div, 0); -static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, - show_fan_div, store_fan_div, 1); -static SENSOR_DEVICE_ATTR(fan3_div, S_IRUGO | S_IWUSR, - show_fan_div, store_fan_div, 2); - -static ssize_t -show_pwm(struct device *dev, struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%d\n", (int)data->pwm[attr->index]); -} - -static ssize_t -show_pwm2_enable(struct device *dev, struct device_attribute *da, char *buf) -{ - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%d\n", (int)data->pwm2_enable); -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *da, const char *buf, - size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); - w83781d_write_value(data, W83781D_REG_PWM[nr], data->pwm[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_pwm2_enable(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - unsigned long val; - u32 reg; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - switch (val) { - case 0: - case 1: - reg = w83781d_read_value(data, W83781D_REG_PWMCLK12); - w83781d_write_value(data, W83781D_REG_PWMCLK12, - (reg & 0xf7) | (val << 3)); - - reg = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); - w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, - (reg & 0xef) | (!val << 4)); - - data->pwm2_enable = val; - break; - - default: - mutex_unlock(&data->update_lock); - return -EINVAL; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm4, S_IRUGO | S_IWUSR, show_pwm, store_pwm, 3); -/* only PWM2 can be enabled/disabled */ -static DEVICE_ATTR(pwm2_enable, S_IRUGO | S_IWUSR, - show_pwm2_enable, store_pwm2_enable); - -static ssize_t -show_sensor(struct device *dev, struct device_attribute *da, char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = w83781d_update_device(dev); - return sprintf(buf, "%d\n", (int)data->sens[attr->index]); -} - -static ssize_t -store_sensor(struct device *dev, struct device_attribute *da, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct w83781d_data *data = dev_get_drvdata(dev); - int nr = attr->index; - unsigned long val; - u32 tmp; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - switch (val) { - case 1: /* PII/Celeron diode */ - tmp = w83781d_read_value(data, W83781D_REG_SCFG1); - w83781d_write_value(data, W83781D_REG_SCFG1, - tmp | BIT_SCFG1[nr]); - tmp = w83781d_read_value(data, W83781D_REG_SCFG2); - w83781d_write_value(data, W83781D_REG_SCFG2, - tmp | BIT_SCFG2[nr]); - data->sens[nr] = val; - break; - case 2: /* 3904 */ - tmp = w83781d_read_value(data, W83781D_REG_SCFG1); - w83781d_write_value(data, W83781D_REG_SCFG1, - tmp | BIT_SCFG1[nr]); - tmp = w83781d_read_value(data, W83781D_REG_SCFG2); - w83781d_write_value(data, W83781D_REG_SCFG2, - tmp & ~BIT_SCFG2[nr]); - data->sens[nr] = val; - break; - case W83781D_DEFAULT_BETA: - dev_warn(dev, "Sensor type %d is deprecated, please use 4 " - "instead\n", W83781D_DEFAULT_BETA); - /* fall through */ - case 4: /* thermistor */ - tmp = w83781d_read_value(data, W83781D_REG_SCFG1); - w83781d_write_value(data, W83781D_REG_SCFG1, - tmp & ~BIT_SCFG1[nr]); - data->sens[nr] = val; - break; - default: - dev_err(dev, "Invalid sensor type %ld; must be 1, 2, or 4\n", - (long) val); - break; - } - - mutex_unlock(&data->update_lock); - return count; -} - -static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR, - show_sensor, store_sensor, 0); -static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR, - show_sensor, store_sensor, 1); -static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR, - show_sensor, store_sensor, 2); - -/* - * Assumes that adapter is of I2C, not ISA variety. - * OTHERWISE DON'T CALL THIS - */ -static int -w83781d_detect_subclients(struct i2c_client *new_client) -{ - int i, val1 = 0, id; - int err; - int address = new_client->addr; - unsigned short sc_addr[2]; - struct i2c_adapter *adapter = new_client->adapter; - struct w83781d_data *data = i2c_get_clientdata(new_client); - enum chips kind = data->type; - - id = i2c_adapter_id(adapter); - - if (force_subclients[0] == id && force_subclients[1] == address) { - for (i = 2; i <= 3; i++) { - if (force_subclients[i] < 0x48 || - force_subclients[i] > 0x4f) { - dev_err(&new_client->dev, "Invalid subclient " - "address %d; must be 0x48-0x4f\n", - force_subclients[i]); - err = -EINVAL; - goto ERROR_SC_1; - } - } - w83781d_write_value(data, W83781D_REG_I2C_SUBADDR, - (force_subclients[2] & 0x07) | - ((force_subclients[3] & 0x07) << 4)); - sc_addr[0] = force_subclients[2]; - } else { - val1 = w83781d_read_value(data, W83781D_REG_I2C_SUBADDR); - sc_addr[0] = 0x48 + (val1 & 0x07); - } - - if (kind != w83783s) { - if (force_subclients[0] == id && - force_subclients[1] == address) { - sc_addr[1] = force_subclients[3]; - } else { - sc_addr[1] = 0x48 + ((val1 >> 4) & 0x07); - } - if (sc_addr[0] == sc_addr[1]) { - dev_err(&new_client->dev, - "Duplicate addresses 0x%x for subclients.\n", - sc_addr[0]); - err = -EBUSY; - goto ERROR_SC_2; - } - } - - for (i = 0; i <= 1; i++) { - data->lm75[i] = i2c_new_dummy(adapter, sc_addr[i]); - if (!data->lm75[i]) { - dev_err(&new_client->dev, "Subclient %d " - "registration at address 0x%x " - "failed.\n", i, sc_addr[i]); - err = -ENOMEM; - if (i == 1) - goto ERROR_SC_3; - goto ERROR_SC_2; - } - if (kind == w83783s) - break; - } - - return 0; - -/* Undo inits in case of errors */ -ERROR_SC_3: - i2c_unregister_device(data->lm75[0]); -ERROR_SC_2: -ERROR_SC_1: - return err; -} - -#define IN_UNIT_ATTRS(X) \ - &sensor_dev_attr_in##X##_input.dev_attr.attr, \ - &sensor_dev_attr_in##X##_min.dev_attr.attr, \ - &sensor_dev_attr_in##X##_max.dev_attr.attr, \ - &sensor_dev_attr_in##X##_alarm.dev_attr.attr, \ - &sensor_dev_attr_in##X##_beep.dev_attr.attr - -#define FAN_UNIT_ATTRS(X) \ - &sensor_dev_attr_fan##X##_input.dev_attr.attr, \ - &sensor_dev_attr_fan##X##_min.dev_attr.attr, \ - &sensor_dev_attr_fan##X##_div.dev_attr.attr, \ - &sensor_dev_attr_fan##X##_alarm.dev_attr.attr, \ - &sensor_dev_attr_fan##X##_beep.dev_attr.attr - -#define TEMP_UNIT_ATTRS(X) \ - &sensor_dev_attr_temp##X##_input.dev_attr.attr, \ - &sensor_dev_attr_temp##X##_max.dev_attr.attr, \ - &sensor_dev_attr_temp##X##_max_hyst.dev_attr.attr, \ - &sensor_dev_attr_temp##X##_alarm.dev_attr.attr, \ - &sensor_dev_attr_temp##X##_beep.dev_attr.attr - -static struct attribute *w83781d_attributes[] = { - IN_UNIT_ATTRS(0), - IN_UNIT_ATTRS(2), - IN_UNIT_ATTRS(3), - IN_UNIT_ATTRS(4), - IN_UNIT_ATTRS(5), - IN_UNIT_ATTRS(6), - FAN_UNIT_ATTRS(1), - FAN_UNIT_ATTRS(2), - FAN_UNIT_ATTRS(3), - TEMP_UNIT_ATTRS(1), - TEMP_UNIT_ATTRS(2), - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - &dev_attr_alarms.attr, - &dev_attr_beep_mask.attr, - &sensor_dev_attr_beep_enable.dev_attr.attr, - NULL -}; -static const struct attribute_group w83781d_group = { - .attrs = w83781d_attributes, -}; - -static struct attribute *w83781d_attributes_in1[] = { - IN_UNIT_ATTRS(1), - NULL -}; -static const struct attribute_group w83781d_group_in1 = { - .attrs = w83781d_attributes_in1, -}; - -static struct attribute *w83781d_attributes_in78[] = { - IN_UNIT_ATTRS(7), - IN_UNIT_ATTRS(8), - NULL -}; -static const struct attribute_group w83781d_group_in78 = { - .attrs = w83781d_attributes_in78, -}; - -static struct attribute *w83781d_attributes_temp3[] = { - TEMP_UNIT_ATTRS(3), - NULL -}; -static const struct attribute_group w83781d_group_temp3 = { - .attrs = w83781d_attributes_temp3, -}; - -static struct attribute *w83781d_attributes_pwm12[] = { - &sensor_dev_attr_pwm1.dev_attr.attr, - &sensor_dev_attr_pwm2.dev_attr.attr, - &dev_attr_pwm2_enable.attr, - NULL -}; -static const struct attribute_group w83781d_group_pwm12 = { - .attrs = w83781d_attributes_pwm12, -}; - -static struct attribute *w83781d_attributes_pwm34[] = { - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm4.dev_attr.attr, - NULL -}; -static const struct attribute_group w83781d_group_pwm34 = { - .attrs = w83781d_attributes_pwm34, -}; - -static struct attribute *w83781d_attributes_other[] = { - &sensor_dev_attr_temp1_type.dev_attr.attr, - &sensor_dev_attr_temp2_type.dev_attr.attr, - &sensor_dev_attr_temp3_type.dev_attr.attr, - NULL -}; -static const struct attribute_group w83781d_group_other = { - .attrs = w83781d_attributes_other, -}; - -/* No clean up is done on error, it's up to the caller */ -static int -w83781d_create_files(struct device *dev, int kind, int is_isa) -{ - int err; - - err = sysfs_create_group(&dev->kobj, &w83781d_group); - if (err) - return err; - - if (kind != w83783s) { - err = sysfs_create_group(&dev->kobj, &w83781d_group_in1); - if (err) - return err; - } - if (kind != as99127f && kind != w83781d && kind != w83783s) { - err = sysfs_create_group(&dev->kobj, &w83781d_group_in78); - if (err) - return err; - } - if (kind != w83783s) { - err = sysfs_create_group(&dev->kobj, &w83781d_group_temp3); - if (err) - return err; - - if (kind != w83781d) { - err = sysfs_chmod_file(&dev->kobj, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - S_IRUGO | S_IWUSR); - if (err) - return err; - } - } - - if (kind != w83781d && kind != as99127f) { - err = sysfs_create_group(&dev->kobj, &w83781d_group_pwm12); - if (err) - return err; - } - if (kind == w83782d && !is_isa) { - err = sysfs_create_group(&dev->kobj, &w83781d_group_pwm34); - if (err) - return err; - } - - if (kind != as99127f && kind != w83781d) { - err = device_create_file(dev, - &sensor_dev_attr_temp1_type.dev_attr); - if (err) - return err; - err = device_create_file(dev, - &sensor_dev_attr_temp2_type.dev_attr); - if (err) - return err; - if (kind != w83783s) { - err = device_create_file(dev, - &sensor_dev_attr_temp3_type.dev_attr); - if (err) - return err; - } - } - - return 0; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int -w83781d_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - int val1, val2; - struct w83781d_data *isa = w83781d_data_if_isa(); - struct i2c_adapter *adapter = client->adapter; - int address = client->addr; - const char *client_name; - enum vendor { winbond, asus } vendid; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* - * We block updates of the ISA device to minimize the risk of - * concurrent access to the same W83781D chip through different - * interfaces. - */ - if (isa) - mutex_lock(&isa->update_lock); - - if (i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG) & 0x80) { - dev_dbg(&adapter->dev, - "Detection of w83781d chip failed at step 3\n"); - goto err_nodev; - } - - val1 = i2c_smbus_read_byte_data(client, W83781D_REG_BANK); - val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); - /* Check for Winbond or Asus ID if in bank 0 */ - if (!(val1 & 0x07) && - ((!(val1 & 0x80) && val2 != 0xa3 && val2 != 0xc3) || - ((val1 & 0x80) && val2 != 0x5c && val2 != 0x12))) { - dev_dbg(&adapter->dev, - "Detection of w83781d chip failed at step 4\n"); - goto err_nodev; - } - /* - * If Winbond SMBus, check address at 0x48. - * Asus doesn't support, except for as99127f rev.2 - */ - if ((!(val1 & 0x80) && val2 == 0xa3) || - ((val1 & 0x80) && val2 == 0x5c)) { - if (i2c_smbus_read_byte_data(client, W83781D_REG_I2C_ADDR) - != address) { - dev_dbg(&adapter->dev, - "Detection of w83781d chip failed at step 5\n"); - goto err_nodev; - } - } - - /* Put it now into bank 0 and Vendor ID High Byte */ - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, - (i2c_smbus_read_byte_data(client, W83781D_REG_BANK) - & 0x78) | 0x80); - - /* Get the vendor ID */ - val2 = i2c_smbus_read_byte_data(client, W83781D_REG_CHIPMAN); - if (val2 == 0x5c) - vendid = winbond; - else if (val2 == 0x12) - vendid = asus; - else { - dev_dbg(&adapter->dev, - "w83781d chip vendor is neither Winbond nor Asus\n"); - goto err_nodev; - } - - /* Determine the chip type. */ - val1 = i2c_smbus_read_byte_data(client, W83781D_REG_WCHIPID); - if ((val1 == 0x10 || val1 == 0x11) && vendid == winbond) - client_name = "w83781d"; - else if (val1 == 0x30 && vendid == winbond) - client_name = "w83782d"; - else if (val1 == 0x40 && vendid == winbond && address == 0x2d) - client_name = "w83783s"; - else if (val1 == 0x31) - client_name = "as99127f"; - else - goto err_nodev; - - if (val1 <= 0x30 && w83781d_alias_detect(client, val1)) { - dev_dbg(&adapter->dev, "Device at 0x%02x appears to " - "be the same as ISA device\n", address); - goto err_nodev; - } - - if (isa) - mutex_unlock(&isa->update_lock); - - strlcpy(info->type, client_name, I2C_NAME_SIZE); - - return 0; - - err_nodev: - if (isa) - mutex_unlock(&isa->update_lock); - return -ENODEV; -} - -static void w83781d_remove_files(struct device *dev) -{ - sysfs_remove_group(&dev->kobj, &w83781d_group); - sysfs_remove_group(&dev->kobj, &w83781d_group_in1); - sysfs_remove_group(&dev->kobj, &w83781d_group_in78); - sysfs_remove_group(&dev->kobj, &w83781d_group_temp3); - sysfs_remove_group(&dev->kobj, &w83781d_group_pwm12); - sysfs_remove_group(&dev->kobj, &w83781d_group_pwm34); - sysfs_remove_group(&dev->kobj, &w83781d_group_other); -} - -static int -w83781d_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - struct w83781d_data *data; - int err; - - data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto ERROR1; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->lock); - mutex_init(&data->update_lock); - - data->type = id->driver_data; - data->client = client; - - /* attach secondary i2c lm75-like clients */ - err = w83781d_detect_subclients(client); - if (err) - goto ERROR3; - - /* Initialize the chip */ - w83781d_init_device(dev); - - /* Register sysfs hooks */ - err = w83781d_create_files(dev, data->type, 0); - if (err) - goto ERROR4; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto ERROR4; - } - - return 0; - -ERROR4: - w83781d_remove_files(dev); - if (data->lm75[0]) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1]) - i2c_unregister_device(data->lm75[1]); -ERROR3: - kfree(data); -ERROR1: - return err; -} - -static int -w83781d_remove(struct i2c_client *client) -{ - struct w83781d_data *data = i2c_get_clientdata(client); - struct device *dev = &client->dev; - - hwmon_device_unregister(data->hwmon_dev); - w83781d_remove_files(dev); - - if (data->lm75[0]) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1]) - i2c_unregister_device(data->lm75[1]); - - kfree(data); - - return 0; -} - -static int -w83781d_read_value_i2c(struct w83781d_data *data, u16 reg) -{ - struct i2c_client *client = data->client; - int res, bank; - struct i2c_client *cl; - - bank = (reg >> 8) & 0x0f; - if (bank > 2) - /* switch banks */ - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, - bank); - if (bank == 0 || bank > 2) { - res = i2c_smbus_read_byte_data(client, reg & 0xff); - } else { - /* switch to subclient */ - cl = data->lm75[bank - 1]; - /* convert from ISA to LM75 I2C addresses */ - switch (reg & 0xff) { - case 0x50: /* TEMP */ - res = i2c_smbus_read_word_swapped(cl, 0); - break; - case 0x52: /* CONFIG */ - res = i2c_smbus_read_byte_data(cl, 1); - break; - case 0x53: /* HYST */ - res = i2c_smbus_read_word_swapped(cl, 2); - break; - case 0x55: /* OVER */ - default: - res = i2c_smbus_read_word_swapped(cl, 3); - break; - } - } - if (bank > 2) - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); - - return res; -} - -static int -w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value) -{ - struct i2c_client *client = data->client; - int bank; - struct i2c_client *cl; - - bank = (reg >> 8) & 0x0f; - if (bank > 2) - /* switch banks */ - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, - bank); - if (bank == 0 || bank > 2) { - i2c_smbus_write_byte_data(client, reg & 0xff, - value & 0xff); - } else { - /* switch to subclient */ - cl = data->lm75[bank - 1]; - /* convert from ISA to LM75 I2C addresses */ - switch (reg & 0xff) { - case 0x52: /* CONFIG */ - i2c_smbus_write_byte_data(cl, 1, value & 0xff); - break; - case 0x53: /* HYST */ - i2c_smbus_write_word_swapped(cl, 2, value); - break; - case 0x55: /* OVER */ - i2c_smbus_write_word_swapped(cl, 3, value); - break; - } - } - if (bank > 2) - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0); - - return 0; -} - -static void -w83781d_init_device(struct device *dev) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - int i, p; - int type = data->type; - u8 tmp; - - if (reset && type != as99127f) { /* - * this resets registers we don't have - * documentation for on the as99127f - */ - /* - * Resetting the chip has been the default for a long time, - * but it causes the BIOS initializations (fan clock dividers, - * thermal sensor types...) to be lost, so it is now optional. - * It might even go away if nobody reports it as being useful, - * as I see very little reason why this would be needed at - * all. - */ - dev_info(dev, "If reset=1 solved a problem you were " - "having, please report!\n"); - - /* save these registers */ - i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); - p = w83781d_read_value(data, W83781D_REG_PWMCLK12); - /* - * Reset all except Watchdog values and last conversion values - * This sets fan-divs to 2, among others - */ - w83781d_write_value(data, W83781D_REG_CONFIG, 0x80); - /* - * Restore the registers and disable power-on abnormal beep. - * This saves FAN 1/2/3 input/output values set by BIOS. - */ - w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); - w83781d_write_value(data, W83781D_REG_PWMCLK12, p); - /* - * Disable master beep-enable (reset turns it on). - * Individual beep_mask should be reset to off but for some - * reason disabling this bit helps some people not get beeped - */ - w83781d_write_value(data, W83781D_REG_BEEP_INTS2, 0); - } - - /* - * Disable power-on abnormal beep, as advised by the datasheet. - * Already done if reset=1. - */ - if (init && !reset && type != as99127f) { - i = w83781d_read_value(data, W83781D_REG_BEEP_CONFIG); - w83781d_write_value(data, W83781D_REG_BEEP_CONFIG, i | 0x80); - } - - data->vrm = vid_which_vrm(); - - if ((type != w83781d) && (type != as99127f)) { - tmp = w83781d_read_value(data, W83781D_REG_SCFG1); - for (i = 1; i <= 3; i++) { - if (!(tmp & BIT_SCFG1[i - 1])) { - data->sens[i - 1] = 4; - } else { - if (w83781d_read_value - (data, - W83781D_REG_SCFG2) & BIT_SCFG2[i - 1]) - data->sens[i - 1] = 1; - else - data->sens[i - 1] = 2; - } - if (type == w83783s && i == 2) - break; - } - } - - if (init && type != as99127f) { - /* Enable temp2 */ - tmp = w83781d_read_value(data, W83781D_REG_TEMP2_CONFIG); - if (tmp & 0x01) { - dev_warn(dev, "Enabling temp2, readings " - "might not make sense\n"); - w83781d_write_value(data, W83781D_REG_TEMP2_CONFIG, - tmp & 0xfe); - } - - /* Enable temp3 */ - if (type != w83783s) { - tmp = w83781d_read_value(data, - W83781D_REG_TEMP3_CONFIG); - if (tmp & 0x01) { - dev_warn(dev, "Enabling temp3, " - "readings might not make sense\n"); - w83781d_write_value(data, - W83781D_REG_TEMP3_CONFIG, tmp & 0xfe); - } - } - } - - /* Start monitoring */ - w83781d_write_value(data, W83781D_REG_CONFIG, - (w83781d_read_value(data, - W83781D_REG_CONFIG) & 0xf7) - | 0x01); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 3; i++) { - data->fan_min[i] = w83781d_read_value(data, - W83781D_REG_FAN_MIN(i)); - } - - mutex_init(&data->update_lock); -} - -static struct w83781d_data *w83781d_update_device(struct device *dev) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - dev_dbg(dev, "Starting device update\n"); - - for (i = 0; i <= 8; i++) { - if (data->type == w83783s && i == 1) - continue; /* 783S has no in1 */ - data->in[i] = - w83781d_read_value(data, W83781D_REG_IN(i)); - data->in_min[i] = - w83781d_read_value(data, W83781D_REG_IN_MIN(i)); - data->in_max[i] = - w83781d_read_value(data, W83781D_REG_IN_MAX(i)); - if ((data->type != w83782d) && (i == 6)) - break; - } - for (i = 0; i < 3; i++) { - data->fan[i] = - w83781d_read_value(data, W83781D_REG_FAN(i)); - data->fan_min[i] = - w83781d_read_value(data, W83781D_REG_FAN_MIN(i)); - } - if (data->type != w83781d && data->type != as99127f) { - for (i = 0; i < 4; i++) { - data->pwm[i] = - w83781d_read_value(data, - W83781D_REG_PWM[i]); - /* Only W83782D on SMBus has PWM3 and PWM4 */ - if ((data->type != w83782d || !client) - && i == 1) - break; - } - /* Only PWM2 can be disabled */ - data->pwm2_enable = (w83781d_read_value(data, - W83781D_REG_PWMCLK12) & 0x08) >> 3; - } - - data->temp = w83781d_read_value(data, W83781D_REG_TEMP(1)); - data->temp_max = - w83781d_read_value(data, W83781D_REG_TEMP_OVER(1)); - data->temp_max_hyst = - w83781d_read_value(data, W83781D_REG_TEMP_HYST(1)); - data->temp_add[0] = - w83781d_read_value(data, W83781D_REG_TEMP(2)); - data->temp_max_add[0] = - w83781d_read_value(data, W83781D_REG_TEMP_OVER(2)); - data->temp_max_hyst_add[0] = - w83781d_read_value(data, W83781D_REG_TEMP_HYST(2)); - if (data->type != w83783s) { - data->temp_add[1] = - w83781d_read_value(data, W83781D_REG_TEMP(3)); - data->temp_max_add[1] = - w83781d_read_value(data, - W83781D_REG_TEMP_OVER(3)); - data->temp_max_hyst_add[1] = - w83781d_read_value(data, - W83781D_REG_TEMP_HYST(3)); - } - i = w83781d_read_value(data, W83781D_REG_VID_FANDIV); - data->vid = i & 0x0f; - data->vid |= (w83781d_read_value(data, - W83781D_REG_CHIPID) & 0x01) << 4; - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = (i >> 6) & 0x03; - data->fan_div[2] = (w83781d_read_value(data, - W83781D_REG_PIN) >> 6) & 0x03; - if ((data->type != w83781d) && (data->type != as99127f)) { - i = w83781d_read_value(data, W83781D_REG_VBAT); - data->fan_div[0] |= (i >> 3) & 0x04; - data->fan_div[1] |= (i >> 4) & 0x04; - data->fan_div[2] |= (i >> 5) & 0x04; - } - if (data->type == w83782d) { - data->alarms = w83781d_read_value(data, - W83782D_REG_ALARM1) - | (w83781d_read_value(data, - W83782D_REG_ALARM2) << 8) - | (w83781d_read_value(data, - W83782D_REG_ALARM3) << 16); - } else if (data->type == w83783s) { - data->alarms = w83781d_read_value(data, - W83782D_REG_ALARM1) - | (w83781d_read_value(data, - W83782D_REG_ALARM2) << 8); - } else { - /* - * No real-time status registers, fall back to - * interrupt status registers - */ - data->alarms = w83781d_read_value(data, - W83781D_REG_ALARM1) - | (w83781d_read_value(data, - W83781D_REG_ALARM2) << 8); - } - i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2); - data->beep_mask = (i << 8) + - w83781d_read_value(data, W83781D_REG_BEEP_INTS1); - if ((data->type != w83781d) && (data->type != as99127f)) { - data->beep_mask |= - w83781d_read_value(data, - W83781D_REG_BEEP_INTS3) << 16; - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -static const struct i2c_device_id w83781d_ids[] = { - { "w83781d", w83781d, }, - { "w83782d", w83782d, }, - { "w83783s", w83783s, }, - { "as99127f", as99127f }, - { /* LIST END */ } -}; -MODULE_DEVICE_TABLE(i2c, w83781d_ids); - -static struct i2c_driver w83781d_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83781d", - }, - .probe = w83781d_probe, - .remove = w83781d_remove, - .id_table = w83781d_ids, - .detect = w83781d_detect, - .address_list = normal_i2c, -}; - -/* - * ISA related code - */ -#ifdef CONFIG_ISA - -/* ISA device, if found */ -static struct platform_device *pdev; - -static unsigned short isa_address = 0x290; - -/* - * I2C devices get this name attribute automatically, but for ISA devices - * we must create it by ourselves. - */ -static ssize_t -show_name(struct device *dev, struct device_attribute *devattr, char *buf) -{ - struct w83781d_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -static struct w83781d_data *w83781d_data_if_isa(void) -{ - return pdev ? platform_get_drvdata(pdev) : NULL; -} - -/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */ -static int w83781d_alias_detect(struct i2c_client *client, u8 chipid) -{ - struct w83781d_data *isa; - int i; - - if (!pdev) /* No ISA chip */ - return 0; - - isa = platform_get_drvdata(pdev); - - if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr) - return 0; /* Address doesn't match */ - if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid) - return 0; /* Chip type doesn't match */ - - /* - * We compare all the limit registers, the config register and the - * interrupt mask registers - */ - for (i = 0x2b; i <= 0x3d; i++) { - if (w83781d_read_value(isa, i) != - i2c_smbus_read_byte_data(client, i)) - return 0; - } - if (w83781d_read_value(isa, W83781D_REG_CONFIG) != - i2c_smbus_read_byte_data(client, W83781D_REG_CONFIG)) - return 0; - for (i = 0x43; i <= 0x46; i++) { - if (w83781d_read_value(isa, i) != - i2c_smbus_read_byte_data(client, i)) - return 0; - } - - return 1; -} - -static int -w83781d_read_value_isa(struct w83781d_data *data, u16 reg) -{ - int word_sized, res; - - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) - && (((reg & 0x00ff) == 0x50) - || ((reg & 0x00ff) == 0x53) - || ((reg & 0x00ff) == 0x55)); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->isa_addr + W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8, - data->isa_addr + W83781D_DATA_REG_OFFSET); - } - outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET); - res = inb_p(data->isa_addr + W83781D_DATA_REG_OFFSET); - if (word_sized) { - outb_p((reg & 0xff) + 1, - data->isa_addr + W83781D_ADDR_REG_OFFSET); - res = - (res << 8) + inb_p(data->isa_addr + - W83781D_DATA_REG_OFFSET); - } - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->isa_addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET); - } - return res; -} - -static void -w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value) -{ - int word_sized; - - word_sized = (((reg & 0xff00) == 0x100) - || ((reg & 0xff00) == 0x200)) - && (((reg & 0x00ff) == 0x53) - || ((reg & 0x00ff) == 0x55)); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->isa_addr + W83781D_ADDR_REG_OFFSET); - outb_p(reg >> 8, - data->isa_addr + W83781D_DATA_REG_OFFSET); - } - outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET); - if (word_sized) { - outb_p(value >> 8, - data->isa_addr + W83781D_DATA_REG_OFFSET); - outb_p((reg & 0xff) + 1, - data->isa_addr + W83781D_ADDR_REG_OFFSET); - } - outb_p(value & 0xff, data->isa_addr + W83781D_DATA_REG_OFFSET); - if (reg & 0xff00) { - outb_p(W83781D_REG_BANK, - data->isa_addr + W83781D_ADDR_REG_OFFSET); - outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET); - } -} - -/* - * The SMBus locks itself, usually, but nothing may access the Winbond between - * bank switches. ISA access must always be locked explicitly! - * We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks, - * would slow down the W83781D access and should not be necessary. - * There are some ugly typecasts here, but the good news is - they should - * nowhere else be necessary! - */ -static int -w83781d_read_value(struct w83781d_data *data, u16 reg) -{ - struct i2c_client *client = data->client; - int res; - - mutex_lock(&data->lock); - if (client) - res = w83781d_read_value_i2c(data, reg); - else - res = w83781d_read_value_isa(data, reg); - mutex_unlock(&data->lock); - return res; -} - -static int -w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) -{ - struct i2c_client *client = data->client; - - mutex_lock(&data->lock); - if (client) - w83781d_write_value_i2c(data, reg, value); - else - w83781d_write_value_isa(data, reg, value); - mutex_unlock(&data->lock); - return 0; -} - -static int __devinit -w83781d_isa_probe(struct platform_device *pdev) -{ - int err, reg; - struct w83781d_data *data; - struct resource *res; - - /* Reserve the ISA region */ - res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2, - "w83781d")) { - err = -EBUSY; - goto exit; - } - - data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release_region; - } - mutex_init(&data->lock); - data->isa_addr = res->start; - platform_set_drvdata(pdev, data); - - reg = w83781d_read_value(data, W83781D_REG_WCHIPID); - switch (reg) { - case 0x30: - data->type = w83782d; - data->name = "w83782d"; - break; - default: - data->type = w83781d; - data->name = "w83781d"; - } - - /* Initialize the W83781D chip */ - w83781d_init_device(&pdev->dev); - - /* Register sysfs hooks */ - err = w83781d_create_files(&pdev->dev, data->type, 1); - if (err) - goto exit_remove_files; - - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_remove_files; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - - exit_remove_files: - w83781d_remove_files(&pdev->dev); - device_remove_file(&pdev->dev, &dev_attr_name); - kfree(data); - exit_release_region: - release_region(res->start + W83781D_ADDR_REG_OFFSET, 2); - exit: - return err; -} - -static int __devexit -w83781d_isa_remove(struct platform_device *pdev) -{ - struct w83781d_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - w83781d_remove_files(&pdev->dev); - device_remove_file(&pdev->dev, &dev_attr_name); - release_region(data->isa_addr + W83781D_ADDR_REG_OFFSET, 2); - kfree(data); - - return 0; -} - -static struct platform_driver w83781d_isa_driver = { - .driver = { - .owner = THIS_MODULE, - .name = "w83781d", - }, - .probe = w83781d_isa_probe, - .remove = __devexit_p(w83781d_isa_remove), -}; - -/* return 1 if a supported chip is found, 0 otherwise */ -static int __init -w83781d_isa_found(unsigned short address) -{ - int val, save, found = 0; - int port; - - /* - * Some boards declare base+0 to base+7 as a PNP device, some base+4 - * to base+7 and some base+5 to base+6. So we better request each port - * individually for the probing phase. - */ - for (port = address; port < address + W83781D_EXTENT; port++) { - if (!request_region(port, 1, "w83781d")) { - pr_debug("Failed to request port 0x%x\n", port); - goto release; - } - } - -#define REALLY_SLOW_IO - /* - * We need the timeouts for at least some W83781D-like - * chips. But only if we read 'undefined' registers. - */ - val = inb_p(address + 1); - if (inb_p(address + 2) != val - || inb_p(address + 3) != val - || inb_p(address + 7) != val) { - pr_debug("Detection failed at step %d\n", 1); - goto release; - } -#undef REALLY_SLOW_IO - - /* - * We should be able to change the 7 LSB of the address port. The - * MSB (busy flag) should be clear initially, set after the write. - */ - save = inb_p(address + W83781D_ADDR_REG_OFFSET); - if (save & 0x80) { - pr_debug("Detection failed at step %d\n", 2); - goto release; - } - val = ~save & 0x7f; - outb_p(val, address + W83781D_ADDR_REG_OFFSET); - if (inb_p(address + W83781D_ADDR_REG_OFFSET) != (val | 0x80)) { - outb_p(save, address + W83781D_ADDR_REG_OFFSET); - pr_debug("Detection failed at step %d\n", 3); - goto release; - } - - /* We found a device, now see if it could be a W83781D */ - outb_p(W83781D_REG_CONFIG, address + W83781D_ADDR_REG_OFFSET); - val = inb_p(address + W83781D_DATA_REG_OFFSET); - if (val & 0x80) { - pr_debug("Detection failed at step %d\n", 4); - goto release; - } - outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); - save = inb_p(address + W83781D_DATA_REG_OFFSET); - outb_p(W83781D_REG_CHIPMAN, address + W83781D_ADDR_REG_OFFSET); - val = inb_p(address + W83781D_DATA_REG_OFFSET); - if ((!(save & 0x80) && (val != 0xa3)) - || ((save & 0x80) && (val != 0x5c))) { - pr_debug("Detection failed at step %d\n", 5); - goto release; - } - outb_p(W83781D_REG_I2C_ADDR, address + W83781D_ADDR_REG_OFFSET); - val = inb_p(address + W83781D_DATA_REG_OFFSET); - if (val < 0x03 || val > 0x77) { /* Not a valid I2C address */ - pr_debug("Detection failed at step %d\n", 6); - goto release; - } - - /* The busy flag should be clear again */ - if (inb_p(address + W83781D_ADDR_REG_OFFSET) & 0x80) { - pr_debug("Detection failed at step %d\n", 7); - goto release; - } - - /* Determine the chip type */ - outb_p(W83781D_REG_BANK, address + W83781D_ADDR_REG_OFFSET); - save = inb_p(address + W83781D_DATA_REG_OFFSET); - outb_p(save & 0xf8, address + W83781D_DATA_REG_OFFSET); - outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET); - val = inb_p(address + W83781D_DATA_REG_OFFSET); - if ((val & 0xfe) == 0x10 /* W83781D */ - || val == 0x30) /* W83782D */ - found = 1; - - if (found) - pr_info("Found a %s chip at %#x\n", - val == 0x30 ? "W83782D" : "W83781D", (int)address); - - release: - for (port--; port >= address; port--) - release_region(port, 1); - return found; -} - -static int __init -w83781d_isa_device_add(unsigned short address) -{ - struct resource res = { - .start = address, - .end = address + W83781D_EXTENT - 1, - .name = "w83781d", - .flags = IORESOURCE_IO, - }; - int err; - - pdev = platform_device_alloc("w83781d", address); - if (!pdev) { - err = -ENOMEM; - pr_err("Device allocation failed\n"); - goto exit; - } - - err = platform_device_add_resources(pdev, &res, 1); - if (err) { - pr_err("Device resource addition failed (%d)\n", err); - goto exit_device_put; - } - - 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: - pdev = NULL; - return err; -} - -static int __init -w83781d_isa_register(void) -{ - int res; - - if (w83781d_isa_found(isa_address)) { - res = platform_driver_register(&w83781d_isa_driver); - if (res) - goto exit; - - /* Sets global pdev as a side effect */ - res = w83781d_isa_device_add(isa_address); - if (res) - goto exit_unreg_isa_driver; - } - - return 0; - -exit_unreg_isa_driver: - platform_driver_unregister(&w83781d_isa_driver); -exit: - return res; -} - -static void -w83781d_isa_unregister(void) -{ - if (pdev) { - platform_device_unregister(pdev); - platform_driver_unregister(&w83781d_isa_driver); - } -} -#else /* !CONFIG_ISA */ - -static struct w83781d_data *w83781d_data_if_isa(void) -{ - return NULL; -} - -static int -w83781d_alias_detect(struct i2c_client *client, u8 chipid) -{ - return 0; -} - -static int -w83781d_read_value(struct w83781d_data *data, u16 reg) -{ - int res; - - mutex_lock(&data->lock); - res = w83781d_read_value_i2c(data, reg); - mutex_unlock(&data->lock); - - return res; -} - -static int -w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value) -{ - mutex_lock(&data->lock); - w83781d_write_value_i2c(data, reg, value); - mutex_unlock(&data->lock); - - return 0; -} - -static int __init -w83781d_isa_register(void) -{ - return 0; -} - -static void -w83781d_isa_unregister(void) -{ -} -#endif /* CONFIG_ISA */ - -static int __init -sensors_w83781d_init(void) -{ - int res; - - /* - * We register the ISA device first, so that we can skip the - * registration of an I2C interface to the same device. - */ - res = w83781d_isa_register(); - if (res) - goto exit; - - res = i2c_add_driver(&w83781d_driver); - if (res) - goto exit_unreg_isa; - - return 0; - - exit_unreg_isa: - w83781d_isa_unregister(); - exit: - return res; -} - -static void __exit -sensors_w83781d_exit(void) -{ - w83781d_isa_unregister(); - i2c_del_driver(&w83781d_driver); -} - -MODULE_AUTHOR("Frodo Looijaard , " - "Philip Edelbrock , " - "and Mark Studebaker "); -MODULE_DESCRIPTION("W83781D driver"); -MODULE_LICENSE("GPL"); - -module_init(sensors_w83781d_init); -module_exit(sensors_w83781d_exit); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83791d.c b/ANDROID_3.4.5/drivers/hwmon/w83791d.c deleted file mode 100644 index 2f446f92..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83791d.c +++ /dev/null @@ -1,1706 +0,0 @@ -/* - * w83791d.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * - * Copyright (C) 2006-2007 Charles Spirakis - * - * 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 following chips: - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * w83791d 10 5 5 3 0x71 0x5ca3 yes no - * - * The w83791d chip appears to be part way between the 83781d and the - * 83792d. Thus, this file is derived from both the w83792d.c and - * w83781d.c files. - * - * The w83791g chip is the same as the w83791d but lead-free. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NUMBER_OF_VIN 10 -#define NUMBER_OF_FANIN 5 -#define NUMBER_OF_TEMPIN 3 -#define NUMBER_OF_PWM 5 - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, - I2C_CLIENT_END }; - -/* Insmod parameters */ - -static unsigned short force_subclients[4]; -module_param_array(force_subclients, short, NULL, 0); -MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); - -static bool reset; -module_param(reset, bool, 0); -MODULE_PARM_DESC(reset, "Set to one to force a hardware chip reset"); - -static bool init; -module_param(init, bool, 0); -MODULE_PARM_DESC(init, "Set to one to force extra software initialization"); - -/* The W83791D registers */ -static const u8 W83791D_REG_IN[NUMBER_OF_VIN] = { - 0x20, /* VCOREA in DataSheet */ - 0x21, /* VINR0 in DataSheet */ - 0x22, /* +3.3VIN in DataSheet */ - 0x23, /* VDD5V in DataSheet */ - 0x24, /* +12VIN in DataSheet */ - 0x25, /* -12VIN in DataSheet */ - 0x26, /* -5VIN in DataSheet */ - 0xB0, /* 5VSB in DataSheet */ - 0xB1, /* VBAT in DataSheet */ - 0xB2 /* VINR1 in DataSheet */ -}; - -static const u8 W83791D_REG_IN_MAX[NUMBER_OF_VIN] = { - 0x2B, /* VCOREA High Limit in DataSheet */ - 0x2D, /* VINR0 High Limit in DataSheet */ - 0x2F, /* +3.3VIN High Limit in DataSheet */ - 0x31, /* VDD5V High Limit in DataSheet */ - 0x33, /* +12VIN High Limit in DataSheet */ - 0x35, /* -12VIN High Limit in DataSheet */ - 0x37, /* -5VIN High Limit in DataSheet */ - 0xB4, /* 5VSB High Limit in DataSheet */ - 0xB6, /* VBAT High Limit in DataSheet */ - 0xB8 /* VINR1 High Limit in DataSheet */ -}; -static const u8 W83791D_REG_IN_MIN[NUMBER_OF_VIN] = { - 0x2C, /* VCOREA Low Limit in DataSheet */ - 0x2E, /* VINR0 Low Limit in DataSheet */ - 0x30, /* +3.3VIN Low Limit in DataSheet */ - 0x32, /* VDD5V Low Limit in DataSheet */ - 0x34, /* +12VIN Low Limit in DataSheet */ - 0x36, /* -12VIN Low Limit in DataSheet */ - 0x38, /* -5VIN Low Limit in DataSheet */ - 0xB5, /* 5VSB Low Limit in DataSheet */ - 0xB7, /* VBAT Low Limit in DataSheet */ - 0xB9 /* VINR1 Low Limit in DataSheet */ -}; -static const u8 W83791D_REG_FAN[NUMBER_OF_FANIN] = { - 0x28, /* FAN 1 Count in DataSheet */ - 0x29, /* FAN 2 Count in DataSheet */ - 0x2A, /* FAN 3 Count in DataSheet */ - 0xBA, /* FAN 4 Count in DataSheet */ - 0xBB, /* FAN 5 Count in DataSheet */ -}; -static const u8 W83791D_REG_FAN_MIN[NUMBER_OF_FANIN] = { - 0x3B, /* FAN 1 Count Low Limit in DataSheet */ - 0x3C, /* FAN 2 Count Low Limit in DataSheet */ - 0x3D, /* FAN 3 Count Low Limit in DataSheet */ - 0xBC, /* FAN 4 Count Low Limit in DataSheet */ - 0xBD, /* FAN 5 Count Low Limit in DataSheet */ -}; - -static const u8 W83791D_REG_PWM[NUMBER_OF_PWM] = { - 0x81, /* PWM 1 duty cycle register in DataSheet */ - 0x83, /* PWM 2 duty cycle register in DataSheet */ - 0x94, /* PWM 3 duty cycle register in DataSheet */ - 0xA0, /* PWM 4 duty cycle register in DataSheet */ - 0xA1, /* PWM 5 duty cycle register in DataSheet */ -}; - -static const u8 W83791D_REG_TEMP_TARGET[3] = { - 0x85, /* PWM 1 target temperature for temp 1 */ - 0x86, /* PWM 2 target temperature for temp 2 */ - 0x96, /* PWM 3 target temperature for temp 3 */ -}; - -static const u8 W83791D_REG_TEMP_TOL[2] = { - 0x87, /* PWM 1/2 temperature tolerance */ - 0x97, /* PWM 3 temperature tolerance */ -}; - -static const u8 W83791D_REG_FAN_CFG[2] = { - 0x84, /* FAN 1/2 configuration */ - 0x95, /* FAN 3 configuration */ -}; - -static const u8 W83791D_REG_FAN_DIV[3] = { - 0x47, /* contains FAN1 and FAN2 Divisor */ - 0x4b, /* contains FAN3 Divisor */ - 0x5C, /* contains FAN4 and FAN5 Divisor */ -}; - -#define W83791D_REG_BANK 0x4E -#define W83791D_REG_TEMP2_CONFIG 0xC2 -#define W83791D_REG_TEMP3_CONFIG 0xCA - -static const u8 W83791D_REG_TEMP1[3] = { - 0x27, /* TEMP 1 in DataSheet */ - 0x39, /* TEMP 1 Over in DataSheet */ - 0x3A, /* TEMP 1 Hyst in DataSheet */ -}; - -static const u8 W83791D_REG_TEMP_ADD[2][6] = { - {0xC0, /* TEMP 2 in DataSheet */ - 0xC1, /* TEMP 2(0.5 deg) in DataSheet */ - 0xC5, /* TEMP 2 Over High part in DataSheet */ - 0xC6, /* TEMP 2 Over Low part in DataSheet */ - 0xC3, /* TEMP 2 Thyst High part in DataSheet */ - 0xC4}, /* TEMP 2 Thyst Low part in DataSheet */ - {0xC8, /* TEMP 3 in DataSheet */ - 0xC9, /* TEMP 3(0.5 deg) in DataSheet */ - 0xCD, /* TEMP 3 Over High part in DataSheet */ - 0xCE, /* TEMP 3 Over Low part in DataSheet */ - 0xCB, /* TEMP 3 Thyst High part in DataSheet */ - 0xCC} /* TEMP 3 Thyst Low part in DataSheet */ -}; - -#define W83791D_REG_BEEP_CONFIG 0x4D - -static const u8 W83791D_REG_BEEP_CTRL[3] = { - 0x56, /* BEEP Control Register 1 */ - 0x57, /* BEEP Control Register 2 */ - 0xA3, /* BEEP Control Register 3 */ -}; - -#define W83791D_REG_GPIO 0x15 -#define W83791D_REG_CONFIG 0x40 -#define W83791D_REG_VID_FANDIV 0x47 -#define W83791D_REG_DID_VID4 0x49 -#define W83791D_REG_WCHIPID 0x58 -#define W83791D_REG_CHIPMAN 0x4F -#define W83791D_REG_PIN 0x4B -#define W83791D_REG_I2C_SUBADDR 0x4A - -#define W83791D_REG_ALARM1 0xA9 /* realtime status register1 */ -#define W83791D_REG_ALARM2 0xAA /* realtime status register2 */ -#define W83791D_REG_ALARM3 0xAB /* realtime status register3 */ - -#define W83791D_REG_VBAT 0x5D -#define W83791D_REG_I2C_ADDR 0x48 - -/* - * The SMBus locks itself. The Winbond W83791D has a bank select register - * (index 0x4e), but the driver only accesses registers in bank 0. Since - * we don't switch banks, we don't need any special code to handle - * locking access between bank switches - */ -static inline int w83791d_read(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static inline int w83791d_write(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -/* - * The analog voltage inputs have 16mV LSB. Since the sysfs output is - * in mV as would be measured on the chip input pin, need to just - * multiply/divide by 16 to translate from/to register values. - */ -#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 8) / 16), 0, 255)) -#define IN_FROM_REG(val) ((val) * 16) - -static u8 fan_to_reg(long rpm, int div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ - ((val) == 255 ? 0 : \ - 1350000 / ((val) * (div)))) - -/* for temp1 which is 8-bit resolution, LSB = 1 degree Celsius */ -#define TEMP1_FROM_REG(val) ((val) * 1000) -#define TEMP1_TO_REG(val) ((val) <= -128000 ? -128 : \ - (val) >= 127000 ? 127 : \ - (val) < 0 ? ((val) - 500) / 1000 : \ - ((val) + 500) / 1000) - -/* - * for temp2 and temp3 which are 9-bit resolution, LSB = 0.5 degree Celsius - * Assumes the top 8 bits are the integral amount and the bottom 8 bits - * are the fractional amount. Since we only have 0.5 degree resolution, - * the bottom 7 bits will always be zero - */ -#define TEMP23_FROM_REG(val) ((val) / 128 * 500) -#define TEMP23_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ - (val) >= 127500 ? 0x7F80 : \ - (val) < 0 ? ((val) - 250) / 500 * 128 : \ - ((val) + 250) / 500 * 128) - -/* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */ -#define TARGET_TEMP_TO_REG(val) ((val) < 0 ? 0 : \ - (val) >= 127000 ? 127 : \ - ((val) + 500) / 1000) - -/* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */ -#define TOL_TEMP_TO_REG(val) ((val) < 0 ? 0 : \ - (val) >= 15000 ? 15 : \ - ((val) + 500) / 1000) - -#define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) -#define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff) - -#define DIV_FROM_REG(val) (1 << (val)) - -static u8 div_to_reg(int nr, long val) -{ - int i; - - /* fan divisors max out at 128 */ - val = SENSORS_LIMIT(val, 1, 128) >> 1; - for (i = 0; i < 7; i++) { - if (val == 0) - break; - val >>= 1; - } - return (u8) i; -} - -struct w83791d_data { - struct device *hwmon_dev; - struct mutex update_lock; - - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* array of 2 pointers to subclients */ - struct i2c_client *lm75[2]; - - /* volts */ - u8 in[NUMBER_OF_VIN]; /* Register value */ - u8 in_max[NUMBER_OF_VIN]; /* Register value */ - u8 in_min[NUMBER_OF_VIN]; /* Register value */ - - /* fans */ - u8 fan[NUMBER_OF_FANIN]; /* Register value */ - u8 fan_min[NUMBER_OF_FANIN]; /* Register value */ - u8 fan_div[NUMBER_OF_FANIN]; /* Register encoding, shifted right */ - - /* Temperature sensors */ - - s8 temp1[3]; /* current, over, thyst */ - s16 temp_add[2][3]; /* fixed point value. Top 8 bits are the - * integral part, bottom 8 bits are the - * fractional part. We only use the top - * 9 bits as the resolution is only - * to the 0.5 degree C... - * two sensors with three values - * (cur, over, hyst) - */ - - /* PWMs */ - u8 pwm[5]; /* pwm duty cycle */ - u8 pwm_enable[3]; /* pwm enable status for fan 1-3 - * (fan 4-5 only support manual mode) - */ - - u8 temp_target[3]; /* pwm 1-3 target temperature */ - u8 temp_tolerance[3]; /* pwm 1-3 temperature tolerance */ - - /* Misc */ - u32 alarms; /* realtime status register encoding,combined */ - u8 beep_enable; /* Global beep enable */ - u32 beep_mask; /* Mask off specific beeps */ - u8 vid; /* Register encoding, combined */ - u8 vrm; /* hwmon-vid */ -}; - -static int w83791d_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83791d_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int w83791d_remove(struct i2c_client *client); - -static int w83791d_read(struct i2c_client *client, u8 reg); -static int w83791d_write(struct i2c_client *client, u8 reg, u8 value); -static struct w83791d_data *w83791d_update_device(struct device *dev); - -#ifdef DEBUG -static void w83791d_print_debug(struct w83791d_data *data, struct device *dev); -#endif - -static void w83791d_init_client(struct i2c_client *client); - -static const struct i2c_device_id w83791d_id[] = { - { "w83791d", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83791d_id); - -static struct i2c_driver w83791d_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83791d", - }, - .probe = w83791d_probe, - .remove = w83791d_remove, - .id_table = w83791d_id, - .detect = w83791d_detect, - .address_list = normal_i2c, -}; - -/* following are the sysfs callback functions */ -#define show_in_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - struct w83791d_data *data = w83791d_update_device(dev); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \ -} - -show_in_reg(in); -show_in_reg(in_min); -show_in_reg(in_max); - -#define store_in_reg(REG, reg) \ -static ssize_t store_in_##reg(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83791d_data *data = i2c_get_clientdata(client); \ - int nr = sensor_attr->index; \ - unsigned long val; \ - int err = kstrtoul(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - w83791d_write(client, W83791D_REG_IN_##REG[nr], data->in_##reg[nr]); \ - mutex_unlock(&data->update_lock); \ - \ - return count; \ -} -store_in_reg(MIN, min); -store_in_reg(MAX, max); - -static struct sensor_device_attribute sda_in_input[] = { - SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), - SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3), - SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4), - SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5), - SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6), - SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7), - SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8), - SENSOR_ATTR(in9_input, S_IRUGO, show_in, NULL, 9), -}; - -static struct sensor_device_attribute sda_in_min[] = { - SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), - SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), - SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), - SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3), - SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4), - SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5), - SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6), - SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7), - SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8), - SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9), -}; - -static struct sensor_device_attribute sda_in_max[] = { - SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), - SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), - SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), - SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3), - SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4), - SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5), - SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6), - SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7), - SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8), - SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9), -}; - - -static ssize_t show_beep(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = - to_sensor_dev_attr(attr); - struct w83791d_data *data = w83791d_update_device(dev); - int bitnr = sensor_attr->index; - - return sprintf(buf, "%d\n", (data->beep_mask >> bitnr) & 1); -} - -static ssize_t store_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = - to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int bitnr = sensor_attr->index; - int bytenr = bitnr / 8; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - val = val ? 1 : 0; - - mutex_lock(&data->update_lock); - - data->beep_mask &= ~(0xff << (bytenr * 8)); - data->beep_mask |= w83791d_read(client, W83791D_REG_BEEP_CTRL[bytenr]) - << (bytenr * 8); - - data->beep_mask &= ~(1 << bitnr); - data->beep_mask |= val << bitnr; - - w83791d_write(client, W83791D_REG_BEEP_CTRL[bytenr], - (data->beep_mask >> (bytenr * 8)) & 0xff); - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = - to_sensor_dev_attr(attr); - struct w83791d_data *data = w83791d_update_device(dev); - int bitnr = sensor_attr->index; - - return sprintf(buf, "%d\n", (data->alarms >> bitnr) & 1); -} - -/* - * Note: The bitmask for the beep enable/disable is different than - * the bitmask for the alarm. - */ -static struct sensor_device_attribute sda_in_beep[] = { - SENSOR_ATTR(in0_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 0), - SENSOR_ATTR(in1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 13), - SENSOR_ATTR(in2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 2), - SENSOR_ATTR(in3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 3), - SENSOR_ATTR(in4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 8), - SENSOR_ATTR(in5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 9), - SENSOR_ATTR(in6_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 10), - SENSOR_ATTR(in7_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 16), - SENSOR_ATTR(in8_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 17), - SENSOR_ATTR(in9_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 14), -}; - -static struct sensor_device_attribute sda_in_alarm[] = { - SENSOR_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0), - SENSOR_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1), - SENSOR_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2), - SENSOR_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 3), - SENSOR_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 8), - SENSOR_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 9), - SENSOR_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 10), - SENSOR_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19), - SENSOR_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20), - SENSOR_ATTR(in9_alarm, S_IRUGO, show_alarm, NULL, 14), -}; - -#define show_fan_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct sensor_device_attribute *sensor_attr = \ - to_sensor_dev_attr(attr); \ - struct w83791d_data *data = w83791d_update_device(dev); \ - int nr = sensor_attr->index; \ - return sprintf(buf, "%d\n", \ - FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ -} - -show_fan_reg(fan); -show_fan_reg(fan_min); - -static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = sensor_attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = fan_to_reg(val, DIV_FROM_REG(data->fan_div[nr])); - w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = sensor_attr->index; - unsigned long min; - u8 tmp_fan_div; - u8 fan_div_reg; - u8 vbat_reg; - int indx = 0; - u8 keep_mask = 0; - u8 new_shift = 0; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - /* Save fan_min */ - min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - - mutex_lock(&data->update_lock); - data->fan_div[nr] = div_to_reg(nr, val); - - switch (nr) { - case 0: - indx = 0; - keep_mask = 0xcf; - new_shift = 4; - break; - case 1: - indx = 0; - keep_mask = 0x3f; - new_shift = 6; - break; - case 2: - indx = 1; - keep_mask = 0x3f; - new_shift = 6; - break; - case 3: - indx = 2; - keep_mask = 0xf8; - new_shift = 0; - break; - case 4: - indx = 2; - keep_mask = 0x8f; - new_shift = 4; - break; -#ifdef DEBUG - default: - dev_warn(dev, "store_fan_div: Unexpected nr seen: %d\n", nr); - count = -EINVAL; - goto err_exit; -#endif - } - - fan_div_reg = w83791d_read(client, W83791D_REG_FAN_DIV[indx]) - & keep_mask; - tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; - - w83791d_write(client, W83791D_REG_FAN_DIV[indx], - fan_div_reg | tmp_fan_div); - - /* Bit 2 of fans 0-2 is stored in the vbat register (bits 5-7) */ - if (nr < 3) { - keep_mask = ~(1 << (nr + 5)); - vbat_reg = w83791d_read(client, W83791D_REG_VBAT) - & keep_mask; - tmp_fan_div = (data->fan_div[nr] << (3 + nr)) & ~keep_mask; - w83791d_write(client, W83791D_REG_VBAT, - vbat_reg | tmp_fan_div); - } - - /* Restore fan_min */ - data->fan_min[nr] = fan_to_reg(min, DIV_FROM_REG(data->fan_div[nr])); - w83791d_write(client, W83791D_REG_FAN_MIN[nr], data->fan_min[nr]); - -#ifdef DEBUG -err_exit: -#endif - 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_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_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 0), - SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 1), - SENSOR_ATTR(fan3_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 2), - SENSOR_ATTR(fan4_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 3), - SENSOR_ATTR(fan5_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 4), -}; - -static struct sensor_device_attribute sda_fan_beep[] = { - SENSOR_ATTR(fan1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 6), - SENSOR_ATTR(fan2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 7), - SENSOR_ATTR(fan3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 11), - SENSOR_ATTR(fan4_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 21), - SENSOR_ATTR(fan5_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 22), -}; - -static struct sensor_device_attribute sda_fan_alarm[] = { - SENSOR_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 6), - SENSOR_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7), - SENSOR_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11), - SENSOR_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21), - SENSOR_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22), -}; - -/* read/write PWMs */ -static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%u\n", data->pwm[nr]); -} - -static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = sensor_attr->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm[nr] = SENSORS_LIMIT(val, 0, 255); - w83791d_write(client, W83791D_REG_PWM[nr], data->pwm[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute sda_pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, - show_pwm, store_pwm, 0), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, - show_pwm, store_pwm, 1), - SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, - show_pwm, store_pwm, 2), - SENSOR_ATTR(pwm4, S_IWUSR | S_IRUGO, - show_pwm, store_pwm, 3), - SENSOR_ATTR(pwm5, S_IWUSR | S_IRUGO, - show_pwm, store_pwm, 4), -}; - -static ssize_t show_pwmenable(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%u\n", data->pwm_enable[nr] + 1); -} - -static ssize_t store_pwmenable(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = sensor_attr->index; - unsigned long val; - u8 reg_cfg_tmp; - u8 reg_idx = 0; - u8 val_shift = 0; - u8 keep_mask = 0; - - int ret = kstrtoul(buf, 10, &val); - - if (ret || val < 1 || val > 3) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm_enable[nr] = val - 1; - switch (nr) { - case 0: - reg_idx = 0; - val_shift = 2; - keep_mask = 0xf3; - break; - case 1: - reg_idx = 0; - val_shift = 4; - keep_mask = 0xcf; - break; - case 2: - reg_idx = 1; - val_shift = 2; - keep_mask = 0xf3; - break; - } - - reg_cfg_tmp = w83791d_read(client, W83791D_REG_FAN_CFG[reg_idx]); - reg_cfg_tmp = (reg_cfg_tmp & keep_mask) | - data->pwm_enable[nr] << val_shift; - - w83791d_write(client, W83791D_REG_FAN_CFG[reg_idx], reg_cfg_tmp); - mutex_unlock(&data->update_lock); - - return count; -} -static struct sensor_device_attribute sda_pwmenable[] = { - SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - show_pwmenable, store_pwmenable, 0), - SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, - show_pwmenable, store_pwmenable, 1), - SENSOR_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, - show_pwmenable, store_pwmenable, 2), -}; - -/* For Smart Fan I / Thermal Cruise */ -static ssize_t show_temp_target(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct w83791d_data *data = w83791d_update_device(dev); - int nr = sensor_attr->index; - return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_target[nr])); -} - -static ssize_t store_temp_target(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = sensor_attr->index; - unsigned long val; - u8 target_mask; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->temp_target[nr] = TARGET_TEMP_TO_REG(val); - target_mask = w83791d_read(client, - W83791D_REG_TEMP_TARGET[nr]) & 0x80; - w83791d_write(client, W83791D_REG_TEMP_TARGET[nr], - data->temp_target[nr] | target_mask); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute sda_temp_target[] = { - SENSOR_ATTR(temp1_target, S_IWUSR | S_IRUGO, - show_temp_target, store_temp_target, 0), - SENSOR_ATTR(temp2_target, S_IWUSR | S_IRUGO, - show_temp_target, store_temp_target, 1), - SENSOR_ATTR(temp3_target, S_IWUSR | S_IRUGO, - show_temp_target, store_temp_target, 2), -}; - -static ssize_t show_temp_tolerance(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct w83791d_data *data = w83791d_update_device(dev); - int nr = sensor_attr->index; - return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp_tolerance[nr])); -} - -static ssize_t store_temp_tolerance(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = sensor_attr->index; - unsigned long val; - u8 target_mask; - u8 reg_idx = 0; - u8 val_shift = 0; - u8 keep_mask = 0; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - - switch (nr) { - case 0: - reg_idx = 0; - val_shift = 0; - keep_mask = 0xf0; - break; - case 1: - reg_idx = 0; - val_shift = 4; - keep_mask = 0x0f; - break; - case 2: - reg_idx = 1; - val_shift = 0; - keep_mask = 0xf0; - break; - } - - mutex_lock(&data->update_lock); - data->temp_tolerance[nr] = TOL_TEMP_TO_REG(val); - target_mask = w83791d_read(client, - W83791D_REG_TEMP_TOL[reg_idx]) & keep_mask; - w83791d_write(client, W83791D_REG_TEMP_TOL[reg_idx], - (data->temp_tolerance[nr] << val_shift) | target_mask); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute sda_temp_tolerance[] = { - SENSOR_ATTR(temp1_tolerance, S_IWUSR | S_IRUGO, - show_temp_tolerance, store_temp_tolerance, 0), - SENSOR_ATTR(temp2_tolerance, S_IWUSR | S_IRUGO, - show_temp_tolerance, store_temp_tolerance, 1), - SENSOR_ATTR(temp3_tolerance, S_IWUSR | S_IRUGO, - show_temp_tolerance, store_temp_tolerance, 2), -}; - -/* read/write the temperature1, includes measured value and limits */ -static ssize_t show_temp1(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[attr->index])); -} - -static ssize_t store_temp1(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int nr = attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp1[nr] = TEMP1_TO_REG(val); - w83791d_write(client, W83791D_REG_TEMP1[nr], data->temp1[nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* read/write temperature2-3, includes measured value and limits */ -static ssize_t show_temp23(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct w83791d_data *data = w83791d_update_device(dev); - int nr = attr->nr; - int index = attr->index; - return sprintf(buf, "%d\n", TEMP23_FROM_REG(data->temp_add[nr][index])); -} - -static ssize_t store_temp23(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - long val; - int err; - int nr = attr->nr; - int index = attr->index; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_add[nr][index] = TEMP23_TO_REG(val); - w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2], - data->temp_add[nr][index] >> 8); - w83791d_write(client, W83791D_REG_TEMP_ADD[nr][index * 2 + 1], - data->temp_add[nr][index] & 0x80); - mutex_unlock(&data->update_lock); - - return count; -} - -static struct sensor_device_attribute_2 sda_temp_input[] = { - SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0), - SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0), - SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0), -}; - -static struct sensor_device_attribute_2 sda_temp_max[] = { - SENSOR_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, - show_temp1, store_temp1, 0, 1), - SENSOR_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, - show_temp23, store_temp23, 0, 1), - SENSOR_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, - show_temp23, store_temp23, 1, 1), -}; - -static struct sensor_device_attribute_2 sda_temp_max_hyst[] = { - SENSOR_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, - show_temp1, store_temp1, 0, 2), - SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, - show_temp23, store_temp23, 0, 2), - SENSOR_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, - show_temp23, store_temp23, 1, 2), -}; - -/* - * Note: The bitmask for the beep enable/disable is different than - * the bitmask for the alarm. - */ -static struct sensor_device_attribute sda_temp_beep[] = { - SENSOR_ATTR(temp1_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 4), - SENSOR_ATTR(temp2_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 5), - SENSOR_ATTR(temp3_beep, S_IWUSR | S_IRUGO, show_beep, store_beep, 1), -}; - -static struct sensor_device_attribute sda_temp_alarm[] = { - SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4), - SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5), - SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13), -}; - -/* get reatime status of all sensors items: voltage, temp, fan */ -static ssize_t show_alarms_reg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%u\n", data->alarms); -} - -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); - -/* Beep control */ - -#define GLOBAL_BEEP_ENABLE_SHIFT 15 -#define GLOBAL_BEEP_ENABLE_MASK (1 << GLOBAL_BEEP_ENABLE_SHIFT) - -static ssize_t show_beep_enable(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%d\n", data->beep_enable); -} - -static ssize_t show_beep_mask(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%d\n", BEEP_MASK_FROM_REG(data->beep_mask)); -} - - -static ssize_t store_beep_mask(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int i; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - /* - * The beep_enable state overrides any enabling request from - * the masks - */ - data->beep_mask = BEEP_MASK_TO_REG(val) & ~GLOBAL_BEEP_ENABLE_MASK; - data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); - - val = data->beep_mask; - - for (i = 0; i < 3; i++) { - w83791d_write(client, W83791D_REG_BEEP_CTRL[i], (val & 0xff)); - val >>= 8; - } - - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t store_beep_enable(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - - data->beep_enable = val ? 1 : 0; - - /* Keep the full mask value in sync with the current enable */ - data->beep_mask &= ~GLOBAL_BEEP_ENABLE_MASK; - data->beep_mask |= (data->beep_enable << GLOBAL_BEEP_ENABLE_SHIFT); - - /* - * The global control is in the second beep control register - * so only need to update that register - */ - val = (data->beep_mask >> 8) & 0xff; - - w83791d_write(client, W83791D_REG_BEEP_CTRL[1], val); - - mutex_unlock(&data->update_lock); - - return count; -} - -static struct sensor_device_attribute sda_beep_ctrl[] = { - SENSOR_ATTR(beep_enable, S_IRUGO | S_IWUSR, - show_beep_enable, store_beep_enable, 0), - SENSOR_ATTR(beep_mask, S_IRUGO | S_IWUSR, - show_beep_mask, store_beep_mask, 1) -}; - -/* cpu voltage regulation information */ -static ssize_t show_vid_reg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83791d_data *data = w83791d_update_device(dev); - return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm)); -} - -static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL); - -static ssize_t show_vrm_reg(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct w83791d_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t store_vrm_reg(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83791d_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - /* - * No lock needed as vrm is internal to the driver - * (not read from a chip register) and so is not - * updated in w83791d_update_device() - */ - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} - -static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm_reg, store_vrm_reg); - -#define IN_UNIT_ATTRS(X) \ - &sda_in_input[X].dev_attr.attr, \ - &sda_in_min[X].dev_attr.attr, \ - &sda_in_max[X].dev_attr.attr, \ - &sda_in_beep[X].dev_attr.attr, \ - &sda_in_alarm[X].dev_attr.attr - -#define FAN_UNIT_ATTRS(X) \ - &sda_fan_input[X].dev_attr.attr, \ - &sda_fan_min[X].dev_attr.attr, \ - &sda_fan_div[X].dev_attr.attr, \ - &sda_fan_beep[X].dev_attr.attr, \ - &sda_fan_alarm[X].dev_attr.attr - -#define TEMP_UNIT_ATTRS(X) \ - &sda_temp_input[X].dev_attr.attr, \ - &sda_temp_max[X].dev_attr.attr, \ - &sda_temp_max_hyst[X].dev_attr.attr, \ - &sda_temp_beep[X].dev_attr.attr, \ - &sda_temp_alarm[X].dev_attr.attr - -static struct attribute *w83791d_attributes[] = { - IN_UNIT_ATTRS(0), - IN_UNIT_ATTRS(1), - IN_UNIT_ATTRS(2), - IN_UNIT_ATTRS(3), - IN_UNIT_ATTRS(4), - IN_UNIT_ATTRS(5), - IN_UNIT_ATTRS(6), - IN_UNIT_ATTRS(7), - IN_UNIT_ATTRS(8), - IN_UNIT_ATTRS(9), - FAN_UNIT_ATTRS(0), - FAN_UNIT_ATTRS(1), - FAN_UNIT_ATTRS(2), - TEMP_UNIT_ATTRS(0), - TEMP_UNIT_ATTRS(1), - TEMP_UNIT_ATTRS(2), - &dev_attr_alarms.attr, - &sda_beep_ctrl[0].dev_attr.attr, - &sda_beep_ctrl[1].dev_attr.attr, - &dev_attr_cpu0_vid.attr, - &dev_attr_vrm.attr, - &sda_pwm[0].dev_attr.attr, - &sda_pwm[1].dev_attr.attr, - &sda_pwm[2].dev_attr.attr, - &sda_pwmenable[0].dev_attr.attr, - &sda_pwmenable[1].dev_attr.attr, - &sda_pwmenable[2].dev_attr.attr, - &sda_temp_target[0].dev_attr.attr, - &sda_temp_target[1].dev_attr.attr, - &sda_temp_target[2].dev_attr.attr, - &sda_temp_tolerance[0].dev_attr.attr, - &sda_temp_tolerance[1].dev_attr.attr, - &sda_temp_tolerance[2].dev_attr.attr, - NULL -}; - -static const struct attribute_group w83791d_group = { - .attrs = w83791d_attributes, -}; - -/* - * Separate group of attributes for fan/pwm 4-5. Their pins can also be - * in use for GPIO in which case their sysfs-interface should not be made - * available - */ -static struct attribute *w83791d_attributes_fanpwm45[] = { - FAN_UNIT_ATTRS(3), - FAN_UNIT_ATTRS(4), - &sda_pwm[3].dev_attr.attr, - &sda_pwm[4].dev_attr.attr, - NULL -}; - -static const struct attribute_group w83791d_group_fanpwm45 = { - .attrs = w83791d_attributes_fanpwm45, -}; - -static int w83791d_detect_subclients(struct i2c_client *client) -{ - struct i2c_adapter *adapter = client->adapter; - struct w83791d_data *data = i2c_get_clientdata(client); - int address = client->addr; - int i, id, err; - u8 val; - - id = i2c_adapter_id(adapter); - if (force_subclients[0] == id && force_subclients[1] == address) { - for (i = 2; i <= 3; i++) { - if (force_subclients[i] < 0x48 || - force_subclients[i] > 0x4f) { - dev_err(&client->dev, - "invalid subclient " - "address %d; must be 0x48-0x4f\n", - force_subclients[i]); - err = -ENODEV; - goto error_sc_0; - } - } - w83791d_write(client, W83791D_REG_I2C_SUBADDR, - (force_subclients[2] & 0x07) | - ((force_subclients[3] & 0x07) << 4)); - } - - val = w83791d_read(client, W83791D_REG_I2C_SUBADDR); - if (!(val & 0x08)) - data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); - if (!(val & 0x80)) { - if ((data->lm75[0] != NULL) && - ((val & 0x7) == ((val >> 4) & 0x7))) { - dev_err(&client->dev, - "duplicate addresses 0x%x, " - "use force_subclient\n", - data->lm75[0]->addr); - err = -ENODEV; - goto error_sc_1; - } - data->lm75[1] = i2c_new_dummy(adapter, - 0x48 + ((val >> 4) & 0x7)); - } - - return 0; - -/* Undo inits in case of errors */ - -error_sc_1: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); -error_sc_0: - return err; -} - - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83791d_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int val1, val2; - unsigned short address = client->addr; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - if (w83791d_read(client, W83791D_REG_CONFIG) & 0x80) - return -ENODEV; - - val1 = w83791d_read(client, W83791D_REG_BANK); - val2 = w83791d_read(client, W83791D_REG_CHIPMAN); - /* Check for Winbond ID if in bank 0 */ - if (!(val1 & 0x07)) { - if ((!(val1 & 0x80) && val2 != 0xa3) || - ((val1 & 0x80) && val2 != 0x5c)) { - return -ENODEV; - } - } - /* - * If Winbond chip, address of chip and W83791D_REG_I2C_ADDR - * should match - */ - if (w83791d_read(client, W83791D_REG_I2C_ADDR) != address) - return -ENODEV; - - /* We want bank 0 and Vendor ID high byte */ - val1 = w83791d_read(client, W83791D_REG_BANK) & 0x78; - w83791d_write(client, W83791D_REG_BANK, val1 | 0x80); - - /* Verify it is a Winbond w83791d */ - val1 = w83791d_read(client, W83791D_REG_WCHIPID); - val2 = w83791d_read(client, W83791D_REG_CHIPMAN); - if (val1 != 0x71 || val2 != 0x5c) - return -ENODEV; - - strlcpy(info->type, "w83791d", I2C_NAME_SIZE); - - return 0; -} - -static int w83791d_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct w83791d_data *data; - struct device *dev = &client->dev; - int i, err; - u8 has_fanpwm45; - -#ifdef DEBUG - int val1; - val1 = w83791d_read(client, W83791D_REG_DID_VID4); - dev_dbg(dev, "Device ID version: %d.%d (0x%02x)\n", - (val1 >> 5) & 0x07, (val1 >> 1) & 0x0f, val1); -#endif - - data = kzalloc(sizeof(struct w83791d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto error0; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - err = w83791d_detect_subclients(client); - if (err) - goto error1; - - /* Initialize the chip */ - w83791d_init_client(client); - - /* - * If the fan_div is changed, make sure there is a rational - * fan_min in place - */ - for (i = 0; i < NUMBER_OF_FANIN; i++) - data->fan_min[i] = w83791d_read(client, W83791D_REG_FAN_MIN[i]); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &w83791d_group); - if (err) - goto error3; - - /* Check if pins of fan/pwm 4-5 are in use as GPIO */ - has_fanpwm45 = w83791d_read(client, W83791D_REG_GPIO) & 0x10; - if (has_fanpwm45) { - err = sysfs_create_group(&client->dev.kobj, - &w83791d_group_fanpwm45); - if (err) - goto error4; - } - - /* Everything is ready, now register the working device */ - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error5; - } - - return 0; - -error5: - if (has_fanpwm45) - sysfs_remove_group(&client->dev.kobj, &w83791d_group_fanpwm45); -error4: - sysfs_remove_group(&client->dev.kobj, &w83791d_group); -error3: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); -error1: - kfree(data); -error0: - return err; -} - -static int w83791d_remove(struct i2c_client *client) -{ - struct w83791d_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83791d_group); - - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); - - kfree(data); - return 0; -} - -static void w83791d_init_client(struct i2c_client *client) -{ - struct w83791d_data *data = i2c_get_clientdata(client); - u8 tmp; - u8 old_beep; - - /* - * The difference between reset and init is that reset - * does a hard reset of the chip via index 0x40, bit 7, - * but init simply forces certain registers to have "sane" - * values. The hope is that the BIOS has done the right - * thing (which is why the default is reset=0, init=0), - * but if not, reset is the hard hammer and init - * is the soft mallet both of which are trying to whack - * things into place... - * NOTE: The data sheet makes a distinction between - * "power on defaults" and "reset by MR". As far as I can tell, - * the hard reset puts everything into a power-on state so I'm - * not sure what "reset by MR" means or how it can happen. - */ - if (reset || init) { - /* keep some BIOS settings when we... */ - old_beep = w83791d_read(client, W83791D_REG_BEEP_CONFIG); - - if (reset) { - /* ... reset the chip and ... */ - w83791d_write(client, W83791D_REG_CONFIG, 0x80); - } - - /* ... disable power-on abnormal beep */ - w83791d_write(client, W83791D_REG_BEEP_CONFIG, old_beep | 0x80); - - /* disable the global beep (not done by hard reset) */ - tmp = w83791d_read(client, W83791D_REG_BEEP_CTRL[1]); - w83791d_write(client, W83791D_REG_BEEP_CTRL[1], tmp & 0xef); - - if (init) { - /* Make sure monitoring is turned on for add-ons */ - tmp = w83791d_read(client, W83791D_REG_TEMP2_CONFIG); - if (tmp & 1) { - w83791d_write(client, W83791D_REG_TEMP2_CONFIG, - tmp & 0xfe); - } - - tmp = w83791d_read(client, W83791D_REG_TEMP3_CONFIG); - if (tmp & 1) { - w83791d_write(client, W83791D_REG_TEMP3_CONFIG, - tmp & 0xfe); - } - - /* Start monitoring */ - tmp = w83791d_read(client, W83791D_REG_CONFIG) & 0xf7; - w83791d_write(client, W83791D_REG_CONFIG, tmp | 0x01); - } - } - - data->vrm = vid_which_vrm(); -} - -static struct w83791d_data *w83791d_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83791d_data *data = i2c_get_clientdata(client); - int i, j; - u8 reg_array_tmp[3]; - u8 vbat_reg; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + (HZ * 3)) - || !data->valid) { - dev_dbg(dev, "Starting w83791d device update\n"); - - /* Update the voltages measured value and limits */ - for (i = 0; i < NUMBER_OF_VIN; i++) { - data->in[i] = w83791d_read(client, - W83791D_REG_IN[i]); - data->in_max[i] = w83791d_read(client, - W83791D_REG_IN_MAX[i]); - data->in_min[i] = w83791d_read(client, - W83791D_REG_IN_MIN[i]); - } - - /* Update the fan counts and limits */ - for (i = 0; i < NUMBER_OF_FANIN; i++) { - /* Update the Fan measured value and limits */ - data->fan[i] = w83791d_read(client, - W83791D_REG_FAN[i]); - data->fan_min[i] = w83791d_read(client, - W83791D_REG_FAN_MIN[i]); - } - - /* Update the fan divisor */ - for (i = 0; i < 3; i++) { - reg_array_tmp[i] = w83791d_read(client, - W83791D_REG_FAN_DIV[i]); - } - data->fan_div[0] = (reg_array_tmp[0] >> 4) & 0x03; - data->fan_div[1] = (reg_array_tmp[0] >> 6) & 0x03; - data->fan_div[2] = (reg_array_tmp[1] >> 6) & 0x03; - data->fan_div[3] = reg_array_tmp[2] & 0x07; - data->fan_div[4] = (reg_array_tmp[2] >> 4) & 0x07; - - /* - * The fan divisor for fans 0-2 get bit 2 from - * bits 5-7 respectively of vbat register - */ - vbat_reg = w83791d_read(client, W83791D_REG_VBAT); - for (i = 0; i < 3; i++) - data->fan_div[i] |= (vbat_reg >> (3 + i)) & 0x04; - - /* Update PWM duty cycle */ - for (i = 0; i < NUMBER_OF_PWM; i++) { - data->pwm[i] = w83791d_read(client, - W83791D_REG_PWM[i]); - } - - /* Update PWM enable status */ - for (i = 0; i < 2; i++) { - reg_array_tmp[i] = w83791d_read(client, - W83791D_REG_FAN_CFG[i]); - } - data->pwm_enable[0] = (reg_array_tmp[0] >> 2) & 0x03; - data->pwm_enable[1] = (reg_array_tmp[0] >> 4) & 0x03; - data->pwm_enable[2] = (reg_array_tmp[1] >> 2) & 0x03; - - /* Update PWM target temperature */ - for (i = 0; i < 3; i++) { - data->temp_target[i] = w83791d_read(client, - W83791D_REG_TEMP_TARGET[i]) & 0x7f; - } - - /* Update PWM temperature tolerance */ - for (i = 0; i < 2; i++) { - reg_array_tmp[i] = w83791d_read(client, - W83791D_REG_TEMP_TOL[i]); - } - data->temp_tolerance[0] = reg_array_tmp[0] & 0x0f; - data->temp_tolerance[1] = (reg_array_tmp[0] >> 4) & 0x0f; - data->temp_tolerance[2] = reg_array_tmp[1] & 0x0f; - - /* Update the first temperature sensor */ - for (i = 0; i < 3; i++) { - data->temp1[i] = w83791d_read(client, - W83791D_REG_TEMP1[i]); - } - - /* Update the rest of the temperature sensors */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - data->temp_add[i][j] = - (w83791d_read(client, - W83791D_REG_TEMP_ADD[i][j * 2]) << 8) | - w83791d_read(client, - W83791D_REG_TEMP_ADD[i][j * 2 + 1]); - } - } - - /* Update the realtime status */ - data->alarms = - w83791d_read(client, W83791D_REG_ALARM1) + - (w83791d_read(client, W83791D_REG_ALARM2) << 8) + - (w83791d_read(client, W83791D_REG_ALARM3) << 16); - - /* Update the beep configuration information */ - data->beep_mask = - w83791d_read(client, W83791D_REG_BEEP_CTRL[0]) + - (w83791d_read(client, W83791D_REG_BEEP_CTRL[1]) << 8) + - (w83791d_read(client, W83791D_REG_BEEP_CTRL[2]) << 16); - - /* Extract global beep enable flag */ - data->beep_enable = - (data->beep_mask >> GLOBAL_BEEP_ENABLE_SHIFT) & 0x01; - - /* Update the cpu voltage information */ - i = w83791d_read(client, W83791D_REG_VID_FANDIV); - data->vid = i & 0x0f; - data->vid |= (w83791d_read(client, W83791D_REG_DID_VID4) & 0x01) - << 4; - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - -#ifdef DEBUG - w83791d_print_debug(data, dev); -#endif - - return data; -} - -#ifdef DEBUG -static void w83791d_print_debug(struct w83791d_data *data, struct device *dev) -{ - int i = 0, j = 0; - - dev_dbg(dev, "======Start of w83791d debug values======\n"); - dev_dbg(dev, "%d set of Voltages: ===>\n", NUMBER_OF_VIN); - for (i = 0; i < NUMBER_OF_VIN; i++) { - dev_dbg(dev, "vin[%d] is: 0x%02x\n", i, data->in[i]); - dev_dbg(dev, "vin[%d] min is: 0x%02x\n", i, data->in_min[i]); - dev_dbg(dev, "vin[%d] max is: 0x%02x\n", i, data->in_max[i]); - } - dev_dbg(dev, "%d set of Fan Counts/Divisors: ===>\n", NUMBER_OF_FANIN); - for (i = 0; i < NUMBER_OF_FANIN; i++) { - dev_dbg(dev, "fan[%d] is: 0x%02x\n", i, data->fan[i]); - dev_dbg(dev, "fan[%d] min is: 0x%02x\n", i, data->fan_min[i]); - dev_dbg(dev, "fan_div[%d] is: 0x%02x\n", i, data->fan_div[i]); - } - - /* - * temperature math is signed, but only print out the - * bits that matter - */ - dev_dbg(dev, "%d set of Temperatures: ===>\n", NUMBER_OF_TEMPIN); - for (i = 0; i < 3; i++) - dev_dbg(dev, "temp1[%d] is: 0x%02x\n", i, (u8) data->temp1[i]); - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - dev_dbg(dev, "temp_add[%d][%d] is: 0x%04x\n", i, j, - (u16) data->temp_add[i][j]); - } - } - - dev_dbg(dev, "Misc Information: ===>\n"); - dev_dbg(dev, "alarm is: 0x%08x\n", data->alarms); - dev_dbg(dev, "beep_mask is: 0x%08x\n", data->beep_mask); - dev_dbg(dev, "beep_enable is: %d\n", data->beep_enable); - dev_dbg(dev, "vid is: 0x%02x\n", data->vid); - dev_dbg(dev, "vrm is: 0x%02x\n", data->vrm); - dev_dbg(dev, "=======End of w83791d debug values========\n"); - dev_dbg(dev, "\n"); -} -#endif - -module_i2c_driver(w83791d_driver); - -MODULE_AUTHOR("Charles Spirakis "); -MODULE_DESCRIPTION("W83791D driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83792d.c b/ANDROID_3.4.5/drivers/hwmon/w83792d.c deleted file mode 100644 index ffb5fdfe..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83792d.c +++ /dev/null @@ -1,1729 +0,0 @@ -/* - * w83792d.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2004, 2005 Winbond Electronics Corp. - * Chunhao Huang , - * Rudolf Marek - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - * - * Note: - * 1. This driver is only for 2.6 kernel, 2.4 kernel need a different driver. - * 2. This driver is only for Winbond W83792D C version device, there - * are also some motherboards with B version W83792D device. The - * calculation method to in6-in7(measured value, limits) is a little - * different between C and B version. C or B version can be identified - * by CR[0x49h]. - */ - -/* - * Supports following chips: - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * w83792d 9 7 7 3 0x7a 0x5ca3 yes no - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, - I2C_CLIENT_END }; - -/* Insmod parameters */ - -static unsigned short force_subclients[4]; -module_param_array(force_subclients, short, NULL, 0); -MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); - -static bool init; -module_param(init, bool, 0); -MODULE_PARM_DESC(init, "Set to one to force chip initialization"); - -/* The W83792D registers */ -static const u8 W83792D_REG_IN[9] = { - 0x20, /* Vcore A in DataSheet */ - 0x21, /* Vcore B in DataSheet */ - 0x22, /* VIN0 in DataSheet */ - 0x23, /* VIN1 in DataSheet */ - 0x24, /* VIN2 in DataSheet */ - 0x25, /* VIN3 in DataSheet */ - 0x26, /* 5VCC in DataSheet */ - 0xB0, /* 5VSB in DataSheet */ - 0xB1 /* VBAT in DataSheet */ -}; -#define W83792D_REG_LOW_BITS1 0x3E /* Low Bits I in DataSheet */ -#define W83792D_REG_LOW_BITS2 0x3F /* Low Bits II in DataSheet */ -static const u8 W83792D_REG_IN_MAX[9] = { - 0x2B, /* Vcore A High Limit in DataSheet */ - 0x2D, /* Vcore B High Limit in DataSheet */ - 0x2F, /* VIN0 High Limit in DataSheet */ - 0x31, /* VIN1 High Limit in DataSheet */ - 0x33, /* VIN2 High Limit in DataSheet */ - 0x35, /* VIN3 High Limit in DataSheet */ - 0x37, /* 5VCC High Limit in DataSheet */ - 0xB4, /* 5VSB High Limit in DataSheet */ - 0xB6 /* VBAT High Limit in DataSheet */ -}; -static const u8 W83792D_REG_IN_MIN[9] = { - 0x2C, /* Vcore A Low Limit in DataSheet */ - 0x2E, /* Vcore B Low Limit in DataSheet */ - 0x30, /* VIN0 Low Limit in DataSheet */ - 0x32, /* VIN1 Low Limit in DataSheet */ - 0x34, /* VIN2 Low Limit in DataSheet */ - 0x36, /* VIN3 Low Limit in DataSheet */ - 0x38, /* 5VCC Low Limit in DataSheet */ - 0xB5, /* 5VSB Low Limit in DataSheet */ - 0xB7 /* VBAT Low Limit in DataSheet */ -}; -static const u8 W83792D_REG_FAN[7] = { - 0x28, /* FAN 1 Count in DataSheet */ - 0x29, /* FAN 2 Count in DataSheet */ - 0x2A, /* FAN 3 Count in DataSheet */ - 0xB8, /* FAN 4 Count in DataSheet */ - 0xB9, /* FAN 5 Count in DataSheet */ - 0xBA, /* FAN 6 Count in DataSheet */ - 0xBE /* FAN 7 Count in DataSheet */ -}; -static const u8 W83792D_REG_FAN_MIN[7] = { - 0x3B, /* FAN 1 Count Low Limit in DataSheet */ - 0x3C, /* FAN 2 Count Low Limit in DataSheet */ - 0x3D, /* FAN 3 Count Low Limit in DataSheet */ - 0xBB, /* FAN 4 Count Low Limit in DataSheet */ - 0xBC, /* FAN 5 Count Low Limit in DataSheet */ - 0xBD, /* FAN 6 Count Low Limit in DataSheet */ - 0xBF /* FAN 7 Count Low Limit in DataSheet */ -}; -#define W83792D_REG_FAN_CFG 0x84 /* FAN Configuration in DataSheet */ -static const u8 W83792D_REG_FAN_DIV[4] = { - 0x47, /* contains FAN2 and FAN1 Divisor */ - 0x5B, /* contains FAN4 and FAN3 Divisor */ - 0x5C, /* contains FAN6 and FAN5 Divisor */ - 0x9E /* contains FAN7 Divisor. */ -}; -static const u8 W83792D_REG_PWM[7] = { - 0x81, /* FAN 1 Duty Cycle, be used to control */ - 0x83, /* FAN 2 Duty Cycle, be used to control */ - 0x94, /* FAN 3 Duty Cycle, be used to control */ - 0xA3, /* FAN 4 Duty Cycle, be used to control */ - 0xA4, /* FAN 5 Duty Cycle, be used to control */ - 0xA5, /* FAN 6 Duty Cycle, be used to control */ - 0xA6 /* FAN 7 Duty Cycle, be used to control */ -}; -#define W83792D_REG_BANK 0x4E -#define W83792D_REG_TEMP2_CONFIG 0xC2 -#define W83792D_REG_TEMP3_CONFIG 0xCA - -static const u8 W83792D_REG_TEMP1[3] = { - 0x27, /* TEMP 1 in DataSheet */ - 0x39, /* TEMP 1 Over in DataSheet */ - 0x3A, /* TEMP 1 Hyst in DataSheet */ -}; - -static const u8 W83792D_REG_TEMP_ADD[2][6] = { - { 0xC0, /* TEMP 2 in DataSheet */ - 0xC1, /* TEMP 2(0.5 deg) in DataSheet */ - 0xC5, /* TEMP 2 Over High part in DataSheet */ - 0xC6, /* TEMP 2 Over Low part in DataSheet */ - 0xC3, /* TEMP 2 Thyst High part in DataSheet */ - 0xC4 }, /* TEMP 2 Thyst Low part in DataSheet */ - { 0xC8, /* TEMP 3 in DataSheet */ - 0xC9, /* TEMP 3(0.5 deg) in DataSheet */ - 0xCD, /* TEMP 3 Over High part in DataSheet */ - 0xCE, /* TEMP 3 Over Low part in DataSheet */ - 0xCB, /* TEMP 3 Thyst High part in DataSheet */ - 0xCC } /* TEMP 3 Thyst Low part in DataSheet */ -}; - -static const u8 W83792D_REG_THERMAL[3] = { - 0x85, /* SmartFanI: Fan1 target value */ - 0x86, /* SmartFanI: Fan2 target value */ - 0x96 /* SmartFanI: Fan3 target value */ -}; - -static const u8 W83792D_REG_TOLERANCE[3] = { - 0x87, /* (bit3-0)SmartFan Fan1 tolerance */ - 0x87, /* (bit7-4)SmartFan Fan2 tolerance */ - 0x97 /* (bit3-0)SmartFan Fan3 tolerance */ -}; - -static const u8 W83792D_REG_POINTS[3][4] = { - { 0x85, /* SmartFanII: Fan1 temp point 1 */ - 0xE3, /* SmartFanII: Fan1 temp point 2 */ - 0xE4, /* SmartFanII: Fan1 temp point 3 */ - 0xE5 }, /* SmartFanII: Fan1 temp point 4 */ - { 0x86, /* SmartFanII: Fan2 temp point 1 */ - 0xE6, /* SmartFanII: Fan2 temp point 2 */ - 0xE7, /* SmartFanII: Fan2 temp point 3 */ - 0xE8 }, /* SmartFanII: Fan2 temp point 4 */ - { 0x96, /* SmartFanII: Fan3 temp point 1 */ - 0xE9, /* SmartFanII: Fan3 temp point 2 */ - 0xEA, /* SmartFanII: Fan3 temp point 3 */ - 0xEB } /* SmartFanII: Fan3 temp point 4 */ -}; - -static const u8 W83792D_REG_LEVELS[3][4] = { - { 0x88, /* (bit3-0) SmartFanII: Fan1 Non-Stop */ - 0x88, /* (bit7-4) SmartFanII: Fan1 Level 1 */ - 0xE0, /* (bit7-4) SmartFanII: Fan1 Level 2 */ - 0xE0 }, /* (bit3-0) SmartFanII: Fan1 Level 3 */ - { 0x89, /* (bit3-0) SmartFanII: Fan2 Non-Stop */ - 0x89, /* (bit7-4) SmartFanII: Fan2 Level 1 */ - 0xE1, /* (bit7-4) SmartFanII: Fan2 Level 2 */ - 0xE1 }, /* (bit3-0) SmartFanII: Fan2 Level 3 */ - { 0x98, /* (bit3-0) SmartFanII: Fan3 Non-Stop */ - 0x98, /* (bit7-4) SmartFanII: Fan3 Level 1 */ - 0xE2, /* (bit7-4) SmartFanII: Fan3 Level 2 */ - 0xE2 } /* (bit3-0) SmartFanII: Fan3 Level 3 */ -}; - -#define W83792D_REG_GPIO_EN 0x1A -#define W83792D_REG_CONFIG 0x40 -#define W83792D_REG_VID_FANDIV 0x47 -#define W83792D_REG_CHIPID 0x49 -#define W83792D_REG_WCHIPID 0x58 -#define W83792D_REG_CHIPMAN 0x4F -#define W83792D_REG_PIN 0x4B -#define W83792D_REG_I2C_SUBADDR 0x4A - -#define W83792D_REG_ALARM1 0xA9 /* realtime status register1 */ -#define W83792D_REG_ALARM2 0xAA /* realtime status register2 */ -#define W83792D_REG_ALARM3 0xAB /* realtime status register3 */ -#define W83792D_REG_CHASSIS 0x42 /* Bit 5: Case Open status bit */ -#define W83792D_REG_CHASSIS_CLR 0x44 /* Bit 7: Case Open CLR_CHS/Reset bit */ - -/* control in0/in1 's limit modifiability */ -#define W83792D_REG_VID_IN_B 0x17 - -#define W83792D_REG_VBAT 0x5D -#define W83792D_REG_I2C_ADDR 0x48 - -/* - * Conversions. Rounding and limit checking is only done on the TO_REG - * variants. Note that you should be a bit careful with which arguments - * these macros are called: arguments may be evaluated more than once. - * Fixing this is just not worth it. - */ -#define IN_FROM_REG(nr, val) (((nr) <= 1) ? ((val) * 2) : \ - ((((nr) == 6) || ((nr) == 7)) ? ((val) * 6) : ((val) * 4))) -#define IN_TO_REG(nr, val) (((nr) <= 1) ? ((val) / 2) : \ - ((((nr) == 6) || ((nr) == 7)) ? ((val) / 6) : ((val) / 4))) - -static inline u8 -FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ - ((val) == 255 ? 0 : \ - 1350000 / ((val) * (div)))) - -/* for temp1 */ -#define TEMP1_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ - : (val)) / 1000, 0, 0xff)) -#define TEMP1_FROM_REG(val) (((val) & 0x80 ? (val)-0x100 : (val)) * 1000) -/* for temp2 and temp3, because they need additional resolution */ -#define TEMP_ADD_FROM_REG(val1, val2) \ - ((((val1) & 0x80 ? (val1)-0x100 \ - : (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0)) -#define TEMP_ADD_TO_REG_HIGH(val) \ - (SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \ - : (val)) / 1000, 0, 0xff)) -#define TEMP_ADD_TO_REG_LOW(val) ((val%1000) ? 0x80 : 0x00) - -#define DIV_FROM_REG(val) (1 << (val)) - -static inline u8 -DIV_TO_REG(long val) -{ - int i; - val = SENSORS_LIMIT(val, 1, 128) >> 1; - for (i = 0; i < 7; i++) { - if (val == 0) - break; - val >>= 1; - } - return (u8)i; -} - -struct w83792d_data { - struct device *hwmon_dev; - - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - - /* array of 2 pointers to subclients */ - struct i2c_client *lm75[2]; - - u8 in[9]; /* Register value */ - u8 in_max[9]; /* Register value */ - u8 in_min[9]; /* Register value */ - u16 low_bits; /* Additional resolution to voltage in6-0 */ - u8 fan[7]; /* Register value */ - u8 fan_min[7]; /* Register value */ - u8 temp1[3]; /* current, over, thyst */ - u8 temp_add[2][6]; /* Register value */ - u8 fan_div[7]; /* Register encoding, shifted right */ - u8 pwm[7]; /* - * We only consider the first 3 set of pwm, - * although 792 chip has 7 set of pwm. - */ - u8 pwmenable[3]; - u32 alarms; /* realtime status register encoding,combined */ - u8 chassis; /* Chassis status */ - u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ - u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */ - u8 tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */ - u8 sf2_points[3][4]; /* Smart FanII: Fan1,2,3 temperature points */ - u8 sf2_levels[3][4]; /* Smart FanII: Fan1,2,3 duty cycle levels */ -}; - -static int w83792d_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83792d_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int w83792d_remove(struct i2c_client *client); -static struct w83792d_data *w83792d_update_device(struct device *dev); - -#ifdef DEBUG -static void w83792d_print_debug(struct w83792d_data *data, struct device *dev); -#endif - -static void w83792d_init_client(struct i2c_client *client); - -static const struct i2c_device_id w83792d_id[] = { - { "w83792d", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83792d_id); - -static struct i2c_driver w83792d_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83792d", - }, - .probe = w83792d_probe, - .remove = w83792d_remove, - .id_table = w83792d_id, - .detect = w83792d_detect, - .address_list = normal_i2c, -}; - -static inline long in_count_from_reg(int nr, struct w83792d_data *data) -{ - /* in7 and in8 do not have low bits, but the formula still works */ - return (data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03); -} - -/* - * The SMBus locks itself. The Winbond W83792D chip has a bank register, - * but the driver only accesses registers in bank 0, so we don't have - * to switch banks and lock access between switches. - */ -static inline int w83792d_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static inline int -w83792d_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -/* following are the sysfs callback functions */ -static ssize_t show_in(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", - IN_FROM_REG(nr, in_count_from_reg(nr, data))); -} - -#define show_in_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct sensor_device_attribute *sensor_attr \ - = to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - struct w83792d_data *data = w83792d_update_device(dev); \ - return sprintf(buf, "%ld\n", \ - (long)(IN_FROM_REG(nr, data->reg[nr]) * 4)); \ -} - -show_in_reg(in_min); -show_in_reg(in_max); - -#define store_in_reg(REG, reg) \ -static ssize_t store_in_##reg(struct device *dev, \ - struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - struct sensor_device_attribute *sensor_attr \ - = to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index; \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83792d_data *data = i2c_get_clientdata(client); \ - unsigned long val; \ - int err = kstrtoul(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = SENSORS_LIMIT(IN_TO_REG(nr, val) / 4, 0, 255); \ - w83792d_write_value(client, W83792D_REG_IN_##REG[nr], \ - data->in_##reg[nr]); \ - mutex_unlock(&data->update_lock); \ - \ - return count; \ -} -store_in_reg(MIN, min); -store_in_reg(MAX, max); - -#define show_fan_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct sensor_device_attribute *sensor_attr \ - = to_sensor_dev_attr(attr); \ - int nr = sensor_attr->index - 1; \ - struct w83792d_data *data = w83792d_update_device(dev); \ - return sprintf(buf, "%d\n", \ - FAN_FROM_REG(data->reg[nr], DIV_FROM_REG(data->fan_div[nr]))); \ -} - -show_fan_reg(fan); -show_fan_reg(fan_min); - -static ssize_t -store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], - data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr - 1])); -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t -store_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long min; - /*u8 reg;*/ - u8 fan_div_reg = 0; - u8 tmp_fan_div; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - /* Save fan_min */ - mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], - DIV_FROM_REG(data->fan_div[nr])); - - data->fan_div[nr] = DIV_TO_REG(val); - - fan_div_reg = w83792d_read_value(client, W83792D_REG_FAN_DIV[nr >> 1]); - fan_div_reg &= (nr & 0x01) ? 0x8f : 0xf8; - tmp_fan_div = (nr & 0x01) ? (((data->fan_div[nr]) << 4) & 0x70) - : ((data->fan_div[nr]) & 0x07); - w83792d_write_value(client, W83792D_REG_FAN_DIV[nr >> 1], - fan_div_reg | tmp_fan_div); - - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83792d_write_value(client, W83792D_REG_FAN_MIN[nr], data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* read/write the temperature1, includes measured value and limits */ - -static ssize_t show_temp1(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", TEMP1_FROM_REG(data->temp1[nr])); -} - -static ssize_t store_temp1(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp1[nr] = TEMP1_TO_REG(val); - w83792d_write_value(client, W83792D_REG_TEMP1[nr], - data->temp1[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* read/write the temperature2-3, includes measured value and limits */ - -static ssize_t show_temp23(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr - = to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", - (long)TEMP_ADD_FROM_REG(data->temp_add[nr][index], - data->temp_add[nr][index+1])); -} - -static ssize_t store_temp23(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr - = to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp_add[nr][index] = TEMP_ADD_TO_REG_HIGH(val); - data->temp_add[nr][index+1] = TEMP_ADD_TO_REG_LOW(val); - w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index], - data->temp_add[nr][index]); - w83792d_write_value(client, W83792D_REG_TEMP_ADD[nr][index+1], - data->temp_add[nr][index+1]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* get reatime status of all sensors items: voltage, temp, fan */ -static ssize_t -show_alarms_reg(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->alarms); -} - -static ssize_t show_alarm(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", (data->alarms >> nr) & 1); -} - -static ssize_t -show_pwm(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", (data->pwm[nr] & 0x0f) << 4); -} - -static ssize_t -show_pwmenable(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; - struct w83792d_data *data = w83792d_update_device(dev); - long pwm_enable_tmp = 1; - - switch (data->pwmenable[nr]) { - case 0: - pwm_enable_tmp = 1; /* manual mode */ - break; - case 1: - pwm_enable_tmp = 3; /*thermal cruise/Smart Fan I */ - break; - case 2: - pwm_enable_tmp = 2; /* Smart Fan II */ - break; - } - - return sprintf(buf, "%ld\n", pwm_enable_tmp); -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - val = SENSORS_LIMIT(val, 0, 255) >> 4; - - mutex_lock(&data->update_lock); - val |= w83792d_read_value(client, W83792D_REG_PWM[nr]) & 0xf0; - data->pwm[nr] = val; - w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -store_pwmenable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - u8 fan_cfg_tmp, cfg1_tmp, cfg2_tmp, cfg3_tmp, cfg4_tmp; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val < 1 || val > 3) - return -EINVAL; - - mutex_lock(&data->update_lock); - switch (val) { - case 1: - data->pwmenable[nr] = 0; /* manual mode */ - break; - case 2: - data->pwmenable[nr] = 2; /* Smart Fan II */ - break; - case 3: - data->pwmenable[nr] = 1; /* thermal cruise/Smart Fan I */ - break; - } - cfg1_tmp = data->pwmenable[0]; - cfg2_tmp = (data->pwmenable[1]) << 2; - cfg3_tmp = (data->pwmenable[2]) << 4; - cfg4_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG) & 0xc0; - fan_cfg_tmp = ((cfg4_tmp | cfg3_tmp) | cfg2_tmp) | cfg1_tmp; - w83792d_write_value(client, W83792D_REG_FAN_CFG, fan_cfg_tmp); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_pwm_mode(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->pwm[nr] >> 7); -} - -static ssize_t -store_pwm_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - if (val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->pwm[nr] = w83792d_read_value(client, W83792D_REG_PWM[nr]); - if (val) { /* PWM mode */ - data->pwm[nr] |= 0x80; - } else { /* DC mode */ - data->pwm[nr] &= 0x7f; - } - w83792d_write_value(client, W83792D_REG_PWM[nr], data->pwm[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_chassis(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->chassis); -} - -static ssize_t -show_regs_chassis(struct device *dev, struct device_attribute *attr, - char *buf) -{ - dev_warn(dev, - "Attribute %s is deprecated, use intrusion0_alarm instead\n", - "chassis"); - return show_chassis(dev, attr, buf); -} - -static ssize_t -show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->chassis_clear); -} - -static ssize_t -store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - u8 temp1 = 0, temp2 = 0; - - dev_warn(dev, - "Attribute %s is deprecated, use intrusion0_alarm instead\n", - "chassis_clear"); - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->chassis_clear = SENSORS_LIMIT(val, 0, 1); - temp1 = ((data->chassis_clear) << 7) & 0x80; - temp2 = w83792d_read_value(client, - W83792D_REG_CHASSIS_CLR) & 0x7f; - w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -store_chassis_clear(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long val; - u8 reg; - - if (kstrtoul(buf, 10, &val) || val != 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - reg = w83792d_read_value(client, W83792D_REG_CHASSIS_CLR); - w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, reg | 0x80); - data->valid = 0; /* Force cache refresh */ - mutex_unlock(&data->update_lock); - - return count; -} - -/* For Smart Fan I / Thermal Cruise */ -static ssize_t -show_thermal_cruise(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", (long)data->thermal_cruise[nr-1]); -} - -static ssize_t -store_thermal_cruise(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - u8 target_tmp = 0, target_mask = 0; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - target_tmp = val; - target_tmp = target_tmp & 0x7f; - mutex_lock(&data->update_lock); - target_mask = w83792d_read_value(client, - W83792D_REG_THERMAL[nr]) & 0x80; - data->thermal_cruise[nr] = SENSORS_LIMIT(target_tmp, 0, 255); - w83792d_write_value(client, W83792D_REG_THERMAL[nr], - (data->thermal_cruise[nr]) | target_mask); - mutex_unlock(&data->update_lock); - - return count; -} - -/* For Smart Fan I/Thermal Cruise and Smart Fan II */ -static ssize_t -show_tolerance(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", (long)data->tolerance[nr-1]); -} - -static ssize_t -store_tolerance(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); - int nr = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - u8 tol_tmp, tol_mask; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - tol_mask = w83792d_read_value(client, - W83792D_REG_TOLERANCE[nr]) & ((nr == 1) ? 0x0f : 0xf0); - tol_tmp = SENSORS_LIMIT(val, 0, 15); - tol_tmp &= 0x0f; - data->tolerance[nr] = tol_tmp; - if (nr == 1) - tol_tmp <<= 4; - w83792d_write_value(client, W83792D_REG_TOLERANCE[nr], - tol_mask | tol_tmp); - mutex_unlock(&data->update_lock); - - return count; -} - -/* For Smart Fan II */ -static ssize_t -show_sf2_point(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr - = to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%ld\n", (long)data->sf2_points[index-1][nr-1]); -} - -static ssize_t -store_sf2_point(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr - = to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr - 1; - int index = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - u8 mask_tmp = 0; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->sf2_points[index][nr] = SENSORS_LIMIT(val, 0, 127); - mask_tmp = w83792d_read_value(client, - W83792D_REG_POINTS[index][nr]) & 0x80; - w83792d_write_value(client, W83792D_REG_POINTS[index][nr], - mask_tmp|data->sf2_points[index][nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_sf2_level(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr - = to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", - (((data->sf2_levels[index-1][nr]) * 100) / 15)); -} - -static ssize_t -store_sf2_level(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr - = to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index - 1; - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - u8 mask_tmp = 0, level_tmp = 0; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->sf2_levels[index][nr] = SENSORS_LIMIT((val * 15) / 100, 0, 15); - mask_tmp = w83792d_read_value(client, W83792D_REG_LEVELS[index][nr]) - & ((nr == 3) ? 0xf0 : 0x0f); - if (nr == 3) - level_tmp = data->sf2_levels[index][nr]; - else - level_tmp = data->sf2_levels[index][nr] << 4; - w83792d_write_value(client, W83792D_REG_LEVELS[index][nr], - level_tmp | mask_tmp); - mutex_unlock(&data->update_lock); - - return count; -} - - -static int -w83792d_detect_subclients(struct i2c_client *new_client) -{ - int i, id, err; - int address = new_client->addr; - u8 val; - struct i2c_adapter *adapter = new_client->adapter; - struct w83792d_data *data = i2c_get_clientdata(new_client); - - id = i2c_adapter_id(adapter); - if (force_subclients[0] == id && force_subclients[1] == address) { - for (i = 2; i <= 3; i++) { - if (force_subclients[i] < 0x48 || - force_subclients[i] > 0x4f) { - dev_err(&new_client->dev, "invalid subclient " - "address %d; must be 0x48-0x4f\n", - force_subclients[i]); - err = -ENODEV; - goto ERROR_SC_0; - } - } - w83792d_write_value(new_client, W83792D_REG_I2C_SUBADDR, - (force_subclients[2] & 0x07) | - ((force_subclients[3] & 0x07) << 4)); - } - - val = w83792d_read_value(new_client, W83792D_REG_I2C_SUBADDR); - if (!(val & 0x08)) - data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (val & 0x7)); - if (!(val & 0x80)) { - if ((data->lm75[0] != NULL) && - ((val & 0x7) == ((val >> 4) & 0x7))) { - dev_err(&new_client->dev, "duplicate addresses 0x%x, " - "use force_subclient\n", data->lm75[0]->addr); - err = -ENODEV; - goto ERROR_SC_1; - } - data->lm75[1] = i2c_new_dummy(adapter, - 0x48 + ((val >> 4) & 0x7)); - } - - return 0; - -/* Undo inits in case of errors */ - -ERROR_SC_1: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); -ERROR_SC_0: - return err; -} - -static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0); -static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1); -static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2); -static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3); -static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4); -static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 5); -static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 6); -static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 7); -static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 8); -static SENSOR_DEVICE_ATTR(in0_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 0); -static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 1); -static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 2); -static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 3); -static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 4); -static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 5); -static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 6); -static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 7); -static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO, - show_in_min, store_in_min, 8); -static SENSOR_DEVICE_ATTR(in0_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 0); -static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 1); -static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 2); -static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 3); -static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 4); -static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 5); -static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 6); -static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 7); -static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO, - show_in_max, store_in_max, 8); -static SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp1, NULL, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp23, NULL, 0, 0); -static SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp23, NULL, 1, 0); -static SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, - show_temp1, store_temp1, 0, 1); -static SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp23, - store_temp23, 0, 2); -static SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp23, - store_temp23, 1, 2); -static SENSOR_DEVICE_ATTR_2(temp1_max_hyst, S_IRUGO | S_IWUSR, - show_temp1, store_temp1, 0, 2); -static SENSOR_DEVICE_ATTR_2(temp2_max_hyst, S_IRUGO | S_IWUSR, - show_temp23, store_temp23, 0, 4); -static SENSOR_DEVICE_ATTR_2(temp3_max_hyst, S_IRUGO | S_IWUSR, - show_temp23, store_temp23, 1, 4); -static DEVICE_ATTR(alarms, S_IRUGO, show_alarms_reg, NULL); -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(temp1_alarm, S_IRUGO, show_alarm, NULL, 2); -static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 3); -static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 4); -static SENSOR_DEVICE_ATTR(fan1_alarm, S_IRUGO, show_alarm, NULL, 5); -static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 6); -static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 7); -static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 8); -static SENSOR_DEVICE_ATTR(in3_alarm, S_IRUGO, show_alarm, NULL, 9); -static SENSOR_DEVICE_ATTR(in4_alarm, S_IRUGO, show_alarm, NULL, 10); -static SENSOR_DEVICE_ATTR(in5_alarm, S_IRUGO, show_alarm, NULL, 11); -static SENSOR_DEVICE_ATTR(in6_alarm, S_IRUGO, show_alarm, NULL, 12); -static SENSOR_DEVICE_ATTR(fan7_alarm, S_IRUGO, show_alarm, NULL, 15); -static SENSOR_DEVICE_ATTR(in7_alarm, S_IRUGO, show_alarm, NULL, 19); -static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20); -static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21); -static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); -static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); -static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); -static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, - show_chassis_clear, store_chassis_clear_legacy); -static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, - show_chassis, store_chassis_clear); -static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); -static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); -static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); -static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, - show_pwmenable, store_pwmenable, 1); -static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, - show_pwmenable, store_pwmenable, 2); -static SENSOR_DEVICE_ATTR(pwm3_enable, S_IWUSR | S_IRUGO, - show_pwmenable, store_pwmenable, 3); -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(tolerance1, S_IWUSR | S_IRUGO, - show_tolerance, store_tolerance, 1); -static SENSOR_DEVICE_ATTR(tolerance2, S_IWUSR | S_IRUGO, - show_tolerance, store_tolerance, 2); -static SENSOR_DEVICE_ATTR(tolerance3, S_IWUSR | S_IRUGO, - show_tolerance, store_tolerance, 3); -static SENSOR_DEVICE_ATTR(thermal_cruise1, S_IWUSR | S_IRUGO, - show_thermal_cruise, store_thermal_cruise, 1); -static SENSOR_DEVICE_ATTR(thermal_cruise2, S_IWUSR | S_IRUGO, - show_thermal_cruise, store_thermal_cruise, 2); -static SENSOR_DEVICE_ATTR(thermal_cruise3, S_IWUSR | S_IRUGO, - show_thermal_cruise, store_thermal_cruise, 3); -static SENSOR_DEVICE_ATTR_2(sf2_point1_fan1, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 1, 1); -static SENSOR_DEVICE_ATTR_2(sf2_point2_fan1, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 2, 1); -static SENSOR_DEVICE_ATTR_2(sf2_point3_fan1, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 3, 1); -static SENSOR_DEVICE_ATTR_2(sf2_point4_fan1, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 4, 1); -static SENSOR_DEVICE_ATTR_2(sf2_point1_fan2, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 1, 2); -static SENSOR_DEVICE_ATTR_2(sf2_point2_fan2, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 2, 2); -static SENSOR_DEVICE_ATTR_2(sf2_point3_fan2, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 3, 2); -static SENSOR_DEVICE_ATTR_2(sf2_point4_fan2, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 4, 2); -static SENSOR_DEVICE_ATTR_2(sf2_point1_fan3, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 1, 3); -static SENSOR_DEVICE_ATTR_2(sf2_point2_fan3, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 2, 3); -static SENSOR_DEVICE_ATTR_2(sf2_point3_fan3, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 3, 3); -static SENSOR_DEVICE_ATTR_2(sf2_point4_fan3, S_IRUGO | S_IWUSR, - show_sf2_point, store_sf2_point, 4, 3); -static SENSOR_DEVICE_ATTR_2(sf2_level1_fan1, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 1, 1); -static SENSOR_DEVICE_ATTR_2(sf2_level2_fan1, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 2, 1); -static SENSOR_DEVICE_ATTR_2(sf2_level3_fan1, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 3, 1); -static SENSOR_DEVICE_ATTR_2(sf2_level1_fan2, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 1, 2); -static SENSOR_DEVICE_ATTR_2(sf2_level2_fan2, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 2, 2); -static SENSOR_DEVICE_ATTR_2(sf2_level3_fan2, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 3, 2); -static SENSOR_DEVICE_ATTR_2(sf2_level1_fan3, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 1, 3); -static SENSOR_DEVICE_ATTR_2(sf2_level2_fan3, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 2, 3); -static SENSOR_DEVICE_ATTR_2(sf2_level3_fan3, S_IRUGO | S_IWUSR, - show_sf2_level, store_sf2_level, 3, 3); -static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 1); -static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 2); -static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 3); -static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 4); -static SENSOR_DEVICE_ATTR(fan5_input, S_IRUGO, show_fan, NULL, 5); -static SENSOR_DEVICE_ATTR(fan6_input, S_IRUGO, show_fan, NULL, 6); -static SENSOR_DEVICE_ATTR(fan7_input, S_IRUGO, show_fan, NULL, 7); -static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 1); -static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 2); -static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 3); -static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 4); -static SENSOR_DEVICE_ATTR(fan5_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 5); -static SENSOR_DEVICE_ATTR(fan6_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 6); -static SENSOR_DEVICE_ATTR(fan7_min, S_IWUSR | S_IRUGO, - show_fan_min, store_fan_min, 7); -static SENSOR_DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 1); -static SENSOR_DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 2); -static SENSOR_DEVICE_ATTR(fan3_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 3); -static SENSOR_DEVICE_ATTR(fan4_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 4); -static SENSOR_DEVICE_ATTR(fan5_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 5); -static SENSOR_DEVICE_ATTR(fan6_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 6); -static SENSOR_DEVICE_ATTR(fan7_div, S_IWUSR | S_IRUGO, - show_fan_div, store_fan_div, 7); - -static struct attribute *w83792d_attributes_fan[4][5] = { - { - &sensor_dev_attr_fan4_input.dev_attr.attr, - &sensor_dev_attr_fan4_min.dev_attr.attr, - &sensor_dev_attr_fan4_div.dev_attr.attr, - &sensor_dev_attr_fan4_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan5_input.dev_attr.attr, - &sensor_dev_attr_fan5_min.dev_attr.attr, - &sensor_dev_attr_fan5_div.dev_attr.attr, - &sensor_dev_attr_fan5_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan6_input.dev_attr.attr, - &sensor_dev_attr_fan6_min.dev_attr.attr, - &sensor_dev_attr_fan6_div.dev_attr.attr, - &sensor_dev_attr_fan6_alarm.dev_attr.attr, - NULL - }, { - &sensor_dev_attr_fan7_input.dev_attr.attr, - &sensor_dev_attr_fan7_min.dev_attr.attr, - &sensor_dev_attr_fan7_div.dev_attr.attr, - &sensor_dev_attr_fan7_alarm.dev_attr.attr, - NULL - } -}; - -static const struct attribute_group w83792d_group_fan[4] = { - { .attrs = w83792d_attributes_fan[0] }, - { .attrs = w83792d_attributes_fan[1] }, - { .attrs = w83792d_attributes_fan[2] }, - { .attrs = w83792d_attributes_fan[3] }, -}; - -static struct attribute *w83792d_attributes[] = { - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_max.dev_attr.attr, - &sensor_dev_attr_in0_min.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_max.dev_attr.attr, - &sensor_dev_attr_in1_min.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_max.dev_attr.attr, - &sensor_dev_attr_in2_min.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - &sensor_dev_attr_in3_max.dev_attr.attr, - &sensor_dev_attr_in3_min.dev_attr.attr, - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_max.dev_attr.attr, - &sensor_dev_attr_in4_min.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_max.dev_attr.attr, - &sensor_dev_attr_in5_min.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_max.dev_attr.attr, - &sensor_dev_attr_in6_min.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in7_max.dev_attr.attr, - &sensor_dev_attr_in7_min.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_max.dev_attr.attr, - &sensor_dev_attr_in8_min.dev_attr.attr, - &sensor_dev_attr_in0_alarm.dev_attr.attr, - &sensor_dev_attr_in1_alarm.dev_attr.attr, - &sensor_dev_attr_in2_alarm.dev_attr.attr, - &sensor_dev_attr_in3_alarm.dev_attr.attr, - &sensor_dev_attr_in4_alarm.dev_attr.attr, - &sensor_dev_attr_in5_alarm.dev_attr.attr, - &sensor_dev_attr_in6_alarm.dev_attr.attr, - &sensor_dev_attr_in7_alarm.dev_attr.attr, - &sensor_dev_attr_in8_alarm.dev_attr.attr, - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_max.dev_attr.attr, - &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_max.dev_attr.attr, - &sensor_dev_attr_temp2_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp3_input.dev_attr.attr, - &sensor_dev_attr_temp3_max.dev_attr.attr, - &sensor_dev_attr_temp3_max_hyst.dev_attr.attr, - &sensor_dev_attr_temp1_alarm.dev_attr.attr, - &sensor_dev_attr_temp2_alarm.dev_attr.attr, - &sensor_dev_attr_temp3_alarm.dev_attr.attr, - &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_pwm2.dev_attr.attr, - &sensor_dev_attr_pwm2_mode.dev_attr.attr, - &sensor_dev_attr_pwm2_enable.dev_attr.attr, - &sensor_dev_attr_pwm3.dev_attr.attr, - &sensor_dev_attr_pwm3_mode.dev_attr.attr, - &sensor_dev_attr_pwm3_enable.dev_attr.attr, - &dev_attr_alarms.attr, - &dev_attr_chassis.attr, - &dev_attr_chassis_clear.attr, - &dev_attr_intrusion0_alarm.attr, - &sensor_dev_attr_tolerance1.dev_attr.attr, - &sensor_dev_attr_thermal_cruise1.dev_attr.attr, - &sensor_dev_attr_tolerance2.dev_attr.attr, - &sensor_dev_attr_thermal_cruise2.dev_attr.attr, - &sensor_dev_attr_tolerance3.dev_attr.attr, - &sensor_dev_attr_thermal_cruise3.dev_attr.attr, - &sensor_dev_attr_sf2_point1_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_point2_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_point3_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_point4_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_point1_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_point2_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_point3_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_point4_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_point1_fan3.dev_attr.attr, - &sensor_dev_attr_sf2_point2_fan3.dev_attr.attr, - &sensor_dev_attr_sf2_point3_fan3.dev_attr.attr, - &sensor_dev_attr_sf2_point4_fan3.dev_attr.attr, - &sensor_dev_attr_sf2_level1_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_level2_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_level3_fan1.dev_attr.attr, - &sensor_dev_attr_sf2_level1_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_level2_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_level3_fan2.dev_attr.attr, - &sensor_dev_attr_sf2_level1_fan3.dev_attr.attr, - &sensor_dev_attr_sf2_level2_fan3.dev_attr.attr, - &sensor_dev_attr_sf2_level3_fan3.dev_attr.attr, - &sensor_dev_attr_fan1_input.dev_attr.attr, - &sensor_dev_attr_fan1_min.dev_attr.attr, - &sensor_dev_attr_fan1_div.dev_attr.attr, - &sensor_dev_attr_fan1_alarm.dev_attr.attr, - &sensor_dev_attr_fan2_input.dev_attr.attr, - &sensor_dev_attr_fan2_min.dev_attr.attr, - &sensor_dev_attr_fan2_div.dev_attr.attr, - &sensor_dev_attr_fan2_alarm.dev_attr.attr, - &sensor_dev_attr_fan3_input.dev_attr.attr, - &sensor_dev_attr_fan3_min.dev_attr.attr, - &sensor_dev_attr_fan3_div.dev_attr.attr, - &sensor_dev_attr_fan3_alarm.dev_attr.attr, - NULL -}; - -static const struct attribute_group w83792d_group = { - .attrs = w83792d_attributes, -}; - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int -w83792d_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - int val1, val2; - unsigned short address = client->addr; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - if (w83792d_read_value(client, W83792D_REG_CONFIG) & 0x80) - return -ENODEV; - - val1 = w83792d_read_value(client, W83792D_REG_BANK); - val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); - /* Check for Winbond ID if in bank 0 */ - if (!(val1 & 0x07)) { /* is Bank0 */ - if ((!(val1 & 0x80) && val2 != 0xa3) || - ((val1 & 0x80) && val2 != 0x5c)) - return -ENODEV; - } - /* - * If Winbond chip, address of chip and W83792D_REG_I2C_ADDR - * should match - */ - if (w83792d_read_value(client, W83792D_REG_I2C_ADDR) != address) - return -ENODEV; - - /* Put it now into bank 0 and Vendor ID High Byte */ - w83792d_write_value(client, - W83792D_REG_BANK, - (w83792d_read_value(client, - W83792D_REG_BANK) & 0x78) | 0x80); - - /* Determine the chip type. */ - val1 = w83792d_read_value(client, W83792D_REG_WCHIPID); - val2 = w83792d_read_value(client, W83792D_REG_CHIPMAN); - if (val1 != 0x7a || val2 != 0x5c) - return -ENODEV; - - strlcpy(info->type, "w83792d", I2C_NAME_SIZE); - - return 0; -} - -static int -w83792d_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct w83792d_data *data; - struct device *dev = &client->dev; - int i, val1, err; - - data = kzalloc(sizeof(struct w83792d_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto ERROR0; - } - - i2c_set_clientdata(client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - err = w83792d_detect_subclients(client); - if (err) - goto ERROR1; - - /* Initialize the chip */ - w83792d_init_client(client); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 7; i++) { - data->fan_min[i] = w83792d_read_value(client, - W83792D_REG_FAN_MIN[i]); - } - - /* Register sysfs hooks */ - err = sysfs_create_group(&dev->kobj, &w83792d_group); - if (err) - goto ERROR3; - - /* - * Read GPIO enable register to check if pins for fan 4,5 are used as - * GPIO - */ - val1 = w83792d_read_value(client, W83792D_REG_GPIO_EN); - - if (!(val1 & 0x40)) { - err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[0]); - if (err) - goto exit_remove_files; - } - - if (!(val1 & 0x20)) { - err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[1]); - if (err) - goto exit_remove_files; - } - - val1 = w83792d_read_value(client, W83792D_REG_PIN); - if (val1 & 0x40) { - err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[2]); - if (err) - goto exit_remove_files; - } - - if (val1 & 0x04) { - err = sysfs_create_group(&dev->kobj, &w83792d_group_fan[3]); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&dev->kobj, &w83792d_group); - for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) - sysfs_remove_group(&dev->kobj, &w83792d_group_fan[i]); -ERROR3: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); -ERROR1: - kfree(data); -ERROR0: - return err; -} - -static int -w83792d_remove(struct i2c_client *client) -{ - struct w83792d_data *data = i2c_get_clientdata(client); - int i; - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83792d_group); - for (i = 0; i < ARRAY_SIZE(w83792d_group_fan); i++) - sysfs_remove_group(&client->dev.kobj, - &w83792d_group_fan[i]); - - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); - - kfree(data); - return 0; -} - -static void -w83792d_init_client(struct i2c_client *client) -{ - u8 temp2_cfg, temp3_cfg, vid_in_b; - - if (init) - w83792d_write_value(client, W83792D_REG_CONFIG, 0x80); - - /* - * Clear the bit6 of W83792D_REG_VID_IN_B(set it into 0): - * W83792D_REG_VID_IN_B bit6 = 0: the high/low limit of - * vin0/vin1 can be modified by user; - * W83792D_REG_VID_IN_B bit6 = 1: the high/low limit of - * vin0/vin1 auto-updated, can NOT be modified by user. - */ - vid_in_b = w83792d_read_value(client, W83792D_REG_VID_IN_B); - w83792d_write_value(client, W83792D_REG_VID_IN_B, - vid_in_b & 0xbf); - - temp2_cfg = w83792d_read_value(client, W83792D_REG_TEMP2_CONFIG); - temp3_cfg = w83792d_read_value(client, W83792D_REG_TEMP3_CONFIG); - w83792d_write_value(client, W83792D_REG_TEMP2_CONFIG, - temp2_cfg & 0xe6); - w83792d_write_value(client, W83792D_REG_TEMP3_CONFIG, - temp3_cfg & 0xe6); - - /* Start monitoring */ - w83792d_write_value(client, W83792D_REG_CONFIG, - (w83792d_read_value(client, - W83792D_REG_CONFIG) & 0xf7) - | 0x01); -} - -static struct w83792d_data *w83792d_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - int i, j; - u8 reg_array_tmp[4], reg_tmp; - - mutex_lock(&data->update_lock); - - if (time_after - (jiffies - data->last_updated, (unsigned long) (HZ * 3)) - || time_before(jiffies, data->last_updated) || !data->valid) { - dev_dbg(dev, "Starting device update\n"); - - /* Update the voltages measured value and limits */ - for (i = 0; i < 9; i++) { - data->in[i] = w83792d_read_value(client, - W83792D_REG_IN[i]); - data->in_max[i] = w83792d_read_value(client, - W83792D_REG_IN_MAX[i]); - data->in_min[i] = w83792d_read_value(client, - W83792D_REG_IN_MIN[i]); - } - data->low_bits = w83792d_read_value(client, - W83792D_REG_LOW_BITS1) + - (w83792d_read_value(client, - W83792D_REG_LOW_BITS2) << 8); - for (i = 0; i < 7; i++) { - /* Update the Fan measured value and limits */ - data->fan[i] = w83792d_read_value(client, - W83792D_REG_FAN[i]); - data->fan_min[i] = w83792d_read_value(client, - W83792D_REG_FAN_MIN[i]); - /* Update the PWM/DC Value and PWM/DC flag */ - data->pwm[i] = w83792d_read_value(client, - W83792D_REG_PWM[i]); - } - - reg_tmp = w83792d_read_value(client, W83792D_REG_FAN_CFG); - data->pwmenable[0] = reg_tmp & 0x03; - data->pwmenable[1] = (reg_tmp>>2) & 0x03; - data->pwmenable[2] = (reg_tmp>>4) & 0x03; - - for (i = 0; i < 3; i++) { - data->temp1[i] = w83792d_read_value(client, - W83792D_REG_TEMP1[i]); - } - for (i = 0; i < 2; i++) { - for (j = 0; j < 6; j++) { - data->temp_add[i][j] = w83792d_read_value( - client, W83792D_REG_TEMP_ADD[i][j]); - } - } - - /* Update the Fan Divisor */ - for (i = 0; i < 4; i++) { - reg_array_tmp[i] = w83792d_read_value(client, - W83792D_REG_FAN_DIV[i]); - } - data->fan_div[0] = reg_array_tmp[0] & 0x07; - data->fan_div[1] = (reg_array_tmp[0] >> 4) & 0x07; - data->fan_div[2] = reg_array_tmp[1] & 0x07; - data->fan_div[3] = (reg_array_tmp[1] >> 4) & 0x07; - data->fan_div[4] = reg_array_tmp[2] & 0x07; - data->fan_div[5] = (reg_array_tmp[2] >> 4) & 0x07; - data->fan_div[6] = reg_array_tmp[3] & 0x07; - - /* Update the realtime status */ - data->alarms = w83792d_read_value(client, W83792D_REG_ALARM1) + - (w83792d_read_value(client, W83792D_REG_ALARM2) << 8) + - (w83792d_read_value(client, W83792D_REG_ALARM3) << 16); - - /* Update CaseOpen status and it's CLR_CHS. */ - data->chassis = (w83792d_read_value(client, - W83792D_REG_CHASSIS) >> 5) & 0x01; - data->chassis_clear = (w83792d_read_value(client, - W83792D_REG_CHASSIS_CLR) >> 7) & 0x01; - - /* Update Thermal Cruise/Smart Fan I target value */ - for (i = 0; i < 3; i++) { - data->thermal_cruise[i] = - w83792d_read_value(client, - W83792D_REG_THERMAL[i]) & 0x7f; - } - - /* Update Smart Fan I/II tolerance */ - reg_tmp = w83792d_read_value(client, W83792D_REG_TOLERANCE[0]); - data->tolerance[0] = reg_tmp & 0x0f; - data->tolerance[1] = (reg_tmp >> 4) & 0x0f; - data->tolerance[2] = w83792d_read_value(client, - W83792D_REG_TOLERANCE[2]) & 0x0f; - - /* Update Smart Fan II temperature points */ - for (i = 0; i < 3; i++) { - for (j = 0; j < 4; j++) { - data->sf2_points[i][j] - = w83792d_read_value(client, - W83792D_REG_POINTS[i][j]) & 0x7f; - } - } - - /* Update Smart Fan II duty cycle levels */ - for (i = 0; i < 3; i++) { - reg_tmp = w83792d_read_value(client, - W83792D_REG_LEVELS[i][0]); - data->sf2_levels[i][0] = reg_tmp & 0x0f; - data->sf2_levels[i][1] = (reg_tmp >> 4) & 0x0f; - reg_tmp = w83792d_read_value(client, - W83792D_REG_LEVELS[i][2]); - data->sf2_levels[i][2] = (reg_tmp >> 4) & 0x0f; - data->sf2_levels[i][3] = reg_tmp & 0x0f; - } - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - -#ifdef DEBUG - w83792d_print_debug(data, dev); -#endif - - return data; -} - -#ifdef DEBUG -static void w83792d_print_debug(struct w83792d_data *data, struct device *dev) -{ - int i = 0, j = 0; - dev_dbg(dev, "==========The following is the debug message...========\n"); - dev_dbg(dev, "9 set of Voltages: =====>\n"); - for (i = 0; i < 9; i++) { - dev_dbg(dev, "vin[%d] is: 0x%x\n", i, data->in[i]); - dev_dbg(dev, "vin[%d] max is: 0x%x\n", i, data->in_max[i]); - dev_dbg(dev, "vin[%d] min is: 0x%x\n", i, data->in_min[i]); - } - dev_dbg(dev, "Low Bit1 is: 0x%x\n", data->low_bits & 0xff); - dev_dbg(dev, "Low Bit2 is: 0x%x\n", data->low_bits >> 8); - dev_dbg(dev, "7 set of Fan Counts and Duty Cycles: =====>\n"); - for (i = 0; i < 7; i++) { - dev_dbg(dev, "fan[%d] is: 0x%x\n", i, data->fan[i]); - dev_dbg(dev, "fan[%d] min is: 0x%x\n", i, data->fan_min[i]); - dev_dbg(dev, "pwm[%d] is: 0x%x\n", i, data->pwm[i]); - } - dev_dbg(dev, "3 set of Temperatures: =====>\n"); - for (i = 0; i < 3; i++) - dev_dbg(dev, "temp1[%d] is: 0x%x\n", i, data->temp1[i]); - - for (i = 0; i < 2; i++) { - for (j = 0; j < 6; j++) { - dev_dbg(dev, "temp_add[%d][%d] is: 0x%x\n", i, j, - data->temp_add[i][j]); - } - } - - for (i = 0; i < 7; i++) - dev_dbg(dev, "fan_div[%d] is: 0x%x\n", i, data->fan_div[i]); - - dev_dbg(dev, "==========End of the debug message...================\n"); - dev_dbg(dev, "\n"); -} -#endif - -module_i2c_driver(w83792d_driver); - -MODULE_AUTHOR("Chunhao Huang @ Winbond "); -MODULE_DESCRIPTION("W83792AD/D driver for linux-2.6"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83793.c b/ANDROID_3.4.5/drivers/hwmon/w83793.c deleted file mode 100644 index d6b0bdd4..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83793.c +++ /dev/null @@ -1,2199 +0,0 @@ -/* - * w83793.c - Linux kernel driver for hardware monitoring - * Copyright (C) 2006 Winbond Electronics Corp. - * Yuan Mu - * Rudolf Marek - * Copyright (C) 2009-2010 Sven Anders , ANDURAS AG. - * Watchdog driver part - * (Based partially on fschmd driver, - * Copyright 2007-2008 by Hans de Goede) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation - version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -/* - * Supports following chips: - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * w83793 10 12 8 6 0x7b 0x5ca3 yes no - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Default values */ -#define WATCHDOG_TIMEOUT 2 /* 2 minute default timeout */ - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, 0x2f, - I2C_CLIENT_END }; - -/* Insmod parameters */ - -static unsigned short force_subclients[4]; -module_param_array(force_subclients, short, NULL, 0); -MODULE_PARM_DESC(force_subclients, "List of subclient addresses: " - "{bus, clientaddr, subclientaddr1, subclientaddr2}"); - -static bool reset; -module_param(reset, bool, 0); -MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); - -static int timeout = WATCHDOG_TIMEOUT; /* default timeout in minutes */ -module_param(timeout, int, 0); -MODULE_PARM_DESC(timeout, - "Watchdog timeout in minutes. 2<= timeout <=255 (default=" - __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); - -static bool nowayout = WATCHDOG_NOWAYOUT; -module_param(nowayout, bool, 0); -MODULE_PARM_DESC(nowayout, - "Watchdog cannot be stopped once started (default=" - __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); - -/* - * Address 0x00, 0x0d, 0x0e, 0x0f in all three banks are reserved - * as ID, Bank Select registers - */ -#define W83793_REG_BANKSEL 0x00 -#define W83793_REG_VENDORID 0x0d -#define W83793_REG_CHIPID 0x0e -#define W83793_REG_DEVICEID 0x0f - -#define W83793_REG_CONFIG 0x40 -#define W83793_REG_MFC 0x58 -#define W83793_REG_FANIN_CTRL 0x5c -#define W83793_REG_FANIN_SEL 0x5d -#define W83793_REG_I2C_ADDR 0x0b -#define W83793_REG_I2C_SUBADDR 0x0c -#define W83793_REG_VID_INA 0x05 -#define W83793_REG_VID_INB 0x06 -#define W83793_REG_VID_LATCHA 0x07 -#define W83793_REG_VID_LATCHB 0x08 -#define W83793_REG_VID_CTRL 0x59 - -#define W83793_REG_WDT_LOCK 0x01 -#define W83793_REG_WDT_ENABLE 0x02 -#define W83793_REG_WDT_STATUS 0x03 -#define W83793_REG_WDT_TIMEOUT 0x04 - -static u16 W83793_REG_TEMP_MODE[2] = { 0x5e, 0x5f }; - -#define TEMP_READ 0 -#define TEMP_CRIT 1 -#define TEMP_CRIT_HYST 2 -#define TEMP_WARN 3 -#define TEMP_WARN_HYST 4 -/* - * only crit and crit_hyst affect real-time alarm status - * current crit crit_hyst warn warn_hyst - */ -static u16 W83793_REG_TEMP[][5] = { - {0x1c, 0x78, 0x79, 0x7a, 0x7b}, - {0x1d, 0x7c, 0x7d, 0x7e, 0x7f}, - {0x1e, 0x80, 0x81, 0x82, 0x83}, - {0x1f, 0x84, 0x85, 0x86, 0x87}, - {0x20, 0x88, 0x89, 0x8a, 0x8b}, - {0x21, 0x8c, 0x8d, 0x8e, 0x8f}, -}; - -#define W83793_REG_TEMP_LOW_BITS 0x22 - -#define W83793_REG_BEEP(index) (0x53 + (index)) -#define W83793_REG_ALARM(index) (0x4b + (index)) - -#define W83793_REG_CLR_CHASSIS 0x4a /* SMI MASK4 */ -#define W83793_REG_IRQ_CTRL 0x50 -#define W83793_REG_OVT_CTRL 0x51 -#define W83793_REG_OVT_BEEP 0x52 - -#define IN_READ 0 -#define IN_MAX 1 -#define IN_LOW 2 -static const u16 W83793_REG_IN[][3] = { - /* Current, High, Low */ - {0x10, 0x60, 0x61}, /* Vcore A */ - {0x11, 0x62, 0x63}, /* Vcore B */ - {0x12, 0x64, 0x65}, /* Vtt */ - {0x14, 0x6a, 0x6b}, /* VSEN1 */ - {0x15, 0x6c, 0x6d}, /* VSEN2 */ - {0x16, 0x6e, 0x6f}, /* +3VSEN */ - {0x17, 0x70, 0x71}, /* +12VSEN */ - {0x18, 0x72, 0x73}, /* 5VDD */ - {0x19, 0x74, 0x75}, /* 5VSB */ - {0x1a, 0x76, 0x77}, /* VBAT */ -}; - -/* Low Bits of Vcore A/B Vtt Read/High/Low */ -static const u16 W83793_REG_IN_LOW_BITS[] = { 0x1b, 0x68, 0x69 }; -static u8 scale_in[] = { 2, 2, 2, 16, 16, 16, 8, 24, 24, 16 }; -static u8 scale_in_add[] = { 0, 0, 0, 0, 0, 0, 0, 150, 150, 0 }; - -#define W83793_REG_FAN(index) (0x23 + 2 * (index)) /* High byte */ -#define W83793_REG_FAN_MIN(index) (0x90 + 2 * (index)) /* High byte */ - -#define W83793_REG_PWM_DEFAULT 0xb2 -#define W83793_REG_PWM_ENABLE 0x207 -#define W83793_REG_PWM_UPTIME 0xc3 /* Unit in 0.1 second */ -#define W83793_REG_PWM_DOWNTIME 0xc4 /* Unit in 0.1 second */ -#define W83793_REG_TEMP_CRITICAL 0xc5 - -#define PWM_DUTY 0 -#define PWM_START 1 -#define PWM_NONSTOP 2 -#define PWM_STOP_TIME 3 -#define W83793_REG_PWM(index, nr) (((nr) == 0 ? 0xb3 : \ - (nr) == 1 ? 0x220 : 0x218) + (index)) - -/* bit field, fan1 is bit0, fan2 is bit1 ... */ -#define W83793_REG_TEMP_FAN_MAP(index) (0x201 + (index)) -#define W83793_REG_TEMP_TOL(index) (0x208 + (index)) -#define W83793_REG_TEMP_CRUISE(index) (0x210 + (index)) -#define W83793_REG_PWM_STOP_TIME(index) (0x228 + (index)) -#define W83793_REG_SF2_TEMP(index, nr) (0x230 + ((index) << 4) + (nr)) -#define W83793_REG_SF2_PWM(index, nr) (0x238 + ((index) << 4) + (nr)) - -static inline unsigned long FAN_FROM_REG(u16 val) -{ - if ((val >= 0xfff) || (val == 0)) - return 0; - return 1350000UL / val; -} - -static inline u16 FAN_TO_REG(long rpm) -{ - if (rpm <= 0) - return 0x0fff; - return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe); -} - -static inline unsigned long TIME_FROM_REG(u8 reg) -{ - return reg * 100; -} - -static inline u8 TIME_TO_REG(unsigned long val) -{ - return SENSORS_LIMIT((val + 50) / 100, 0, 0xff); -} - -static inline long TEMP_FROM_REG(s8 reg) -{ - return reg * 1000; -} - -static inline s8 TEMP_TO_REG(long val, s8 min, s8 max) -{ - return SENSORS_LIMIT((val + (val < 0 ? -500 : 500)) / 1000, min, max); -} - -struct w83793_data { - struct i2c_client *lm75[2]; - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - unsigned long last_nonvolatile; /* In jiffies, last time we update the - * nonvolatile registers - */ - - u8 bank; - u8 vrm; - u8 vid[2]; - u8 in[10][3]; /* Register value, read/high/low */ - u8 in_low_bits[3]; /* Additional resolution for VCore A/B Vtt */ - - u16 has_fan; /* Only fan1- fan5 has own pins */ - u16 fan[12]; /* Register value combine */ - u16 fan_min[12]; /* Register value combine */ - - s8 temp[6][5]; /* current, crit, crit_hyst,warn, warn_hyst */ - u8 temp_low_bits; /* Additional resolution TD1-TD4 */ - u8 temp_mode[2]; /* byte 0: Temp D1-D4 mode each has 2 bits - * byte 1: Temp R1,R2 mode, each has 1 bit - */ - u8 temp_critical; /* If reached all fan will be at full speed */ - u8 temp_fan_map[6]; /* Temp controls which pwm fan, bit field */ - - u8 has_pwm; - u8 has_temp; - u8 has_vid; - u8 pwm_enable; /* Register value, each Temp has 1 bit */ - u8 pwm_uptime; /* Register value */ - u8 pwm_downtime; /* Register value */ - u8 pwm_default; /* All fan default pwm, next poweron valid */ - u8 pwm[8][3]; /* Register value */ - u8 pwm_stop_time[8]; - u8 temp_cruise[6]; - - u8 alarms[5]; /* realtime status registers */ - u8 beeps[5]; - u8 beep_enable; - u8 tolerance[3]; /* Temp tolerance(Smart Fan I/II) */ - u8 sf2_pwm[6][7]; /* Smart FanII: Fan duty cycle */ - u8 sf2_temp[6][7]; /* Smart FanII: Temp level point */ - - /* watchdog */ - struct i2c_client *client; - struct mutex watchdog_lock; - struct list_head list; /* member of the watchdog_data_list */ - struct kref kref; - struct miscdevice watchdog_miscdev; - unsigned long watchdog_is_open; - char watchdog_expect_close; - char watchdog_name[10]; /* must be unique to avoid sysfs conflict */ - unsigned int watchdog_caused_reboot; - int watchdog_timeout; /* watchdog timeout in minutes */ -}; - -/* - * Somewhat ugly :( global data pointer list with all devices, so that - * we can find our device data as when using misc_register. There is no - * other method to get to one's device data from the open file-op and - * for usage in the reboot notifier callback. - */ -static LIST_HEAD(watchdog_data_list); - -/* Note this lock not only protect list access, but also data.kref access */ -static DEFINE_MUTEX(watchdog_data_mutex); - -/* - * Release our data struct when we're detached from the i2c client *and* all - * references to our watchdog device are released - */ -static void w83793_release_resources(struct kref *ref) -{ - struct w83793_data *data = container_of(ref, struct w83793_data, kref); - kfree(data); -} - -static u8 w83793_read_value(struct i2c_client *client, u16 reg); -static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value); -static int w83793_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83793_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int w83793_remove(struct i2c_client *client); -static void w83793_init_client(struct i2c_client *client); -static void w83793_update_nonvolatile(struct device *dev); -static struct w83793_data *w83793_update_device(struct device *dev); - -static const struct i2c_device_id w83793_id[] = { - { "w83793", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83793_id); - -static struct i2c_driver w83793_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83793", - }, - .probe = w83793_probe, - .remove = w83793_remove, - .id_table = w83793_id, - .detect = w83793_detect, - .address_list = normal_i2c, -}; - -static ssize_t -show_vrm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83793_data *data = dev_get_drvdata(dev); - return sprintf(buf, "%d\n", data->vrm); -} - -static ssize_t -show_vid(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83793_data *data = w83793_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - - return sprintf(buf, "%d\n", vid_from_reg(data->vid[index], data->vrm)); -} - -static ssize_t -store_vrm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct w83793_data *data = dev_get_drvdata(dev); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - data->vrm = val; - return count; -} - -#define ALARM_STATUS 0 -#define BEEP_ENABLE 1 -static ssize_t -show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83793_data *data = w83793_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index >> 3; - int bit = sensor_attr->index & 0x07; - u8 val; - - if (nr == ALARM_STATUS) { - val = (data->alarms[index] >> (bit)) & 1; - } else { /* BEEP_ENABLE */ - val = (data->beeps[index] >> (bit)) & 1; - } - - return sprintf(buf, "%u\n", val); -} - -static ssize_t -store_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index >> 3; - int shift = sensor_attr->index & 0x07; - u8 beep_bit = 1 << shift; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->beeps[index] = w83793_read_value(client, W83793_REG_BEEP(index)); - data->beeps[index] &= ~beep_bit; - data->beeps[index] |= val << shift; - w83793_write_value(client, W83793_REG_BEEP(index), data->beeps[index]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_beep_enable(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83793_data *data = w83793_update_device(dev); - return sprintf(buf, "%u\n", (data->beep_enable >> 1) & 0x01); -} - -static ssize_t -store_beep_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP) - & 0xfd; - data->beep_enable |= val << 1; - w83793_write_value(client, W83793_REG_OVT_BEEP, data->beep_enable); - mutex_unlock(&data->update_lock); - - return count; -} - -/* Write any value to clear chassis alarm */ -static ssize_t -store_chassis_clear_legacy(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - u8 val; - - dev_warn(dev, "Attribute chassis is deprecated, " - "use intrusion0_alarm instead\n"); - - mutex_lock(&data->update_lock); - val = w83793_read_value(client, W83793_REG_CLR_CHASSIS); - val |= 0x80; - w83793_write_value(client, W83793_REG_CLR_CHASSIS, val); - mutex_unlock(&data->update_lock); - return count; -} - -/* Write 0 to clear chassis alarm */ -static ssize_t -store_chassis_clear(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - unsigned long val; - u8 reg; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - if (val) - return -EINVAL; - - mutex_lock(&data->update_lock); - reg = w83793_read_value(client, W83793_REG_CLR_CHASSIS); - w83793_write_value(client, W83793_REG_CLR_CHASSIS, reg | 0x80); - data->valid = 0; /* Force cache refresh */ - mutex_unlock(&data->update_lock); - return count; -} - -#define FAN_INPUT 0 -#define FAN_MIN 1 -static ssize_t -show_fan(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83793_data *data = w83793_update_device(dev); - u16 val; - - if (nr == FAN_INPUT) - val = data->fan[index] & 0x0fff; - else - val = data->fan_min[index] & 0x0fff; - - return sprintf(buf, "%lu\n", FAN_FROM_REG(val)); -} - -static ssize_t -store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - val = FAN_TO_REG(val); - - mutex_lock(&data->update_lock); - data->fan_min[index] = val; - w83793_write_value(client, W83793_REG_FAN_MIN(index), - (val >> 8) & 0xff); - w83793_write_value(client, W83793_REG_FAN_MIN(index) + 1, val & 0xff); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_pwm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - struct w83793_data *data = w83793_update_device(dev); - u16 val; - int nr = sensor_attr->nr; - int index = sensor_attr->index; - - if (nr == PWM_STOP_TIME) - val = TIME_FROM_REG(data->pwm_stop_time[index]); - else - val = (data->pwm[index][nr] & 0x3f) << 2; - - return sprintf(buf, "%d\n", val); -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (nr == PWM_STOP_TIME) { - val = TIME_TO_REG(val); - data->pwm_stop_time[index] = val; - w83793_write_value(client, W83793_REG_PWM_STOP_TIME(index), - val); - } else { - val = SENSORS_LIMIT(val, 0, 0xff) >> 2; - data->pwm[index][nr] = - w83793_read_value(client, W83793_REG_PWM(index, nr)) & 0xc0; - data->pwm[index][nr] |= val; - w83793_write_value(client, W83793_REG_PWM(index, nr), - data->pwm[index][nr]); - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_temp(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83793_data *data = w83793_update_device(dev); - long temp = TEMP_FROM_REG(data->temp[index][nr]); - - if (nr == TEMP_READ && index < 4) { /* Only TD1-TD4 have low bits */ - int low = ((data->temp_low_bits >> (index * 2)) & 0x03) * 250; - temp += temp > 0 ? low : -low; - } - return sprintf(buf, "%ld\n", temp); -} - -static ssize_t -store_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - long tmp; - int err; - - err = kstrtol(buf, 10, &tmp); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp[index][nr] = TEMP_TO_REG(tmp, -128, 127); - w83793_write_value(client, W83793_REG_TEMP[index][nr], - data->temp[index][nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* - * TD1-TD4 - * each has 4 mode:(2 bits) - * 0: Stop monitor - * 1: Use internal temp sensor(default) - * 2: Reserved - * 3: Use sensor in Intel CPU and get result by PECI - * - * TR1-TR2 - * each has 2 mode:(1 bit) - * 0: Disable temp sensor monitor - * 1: To enable temp sensors monitor - */ - -/* 0 disable, 6 PECI */ -static u8 TO_TEMP_MODE[] = { 0, 0, 0, 6 }; - -static ssize_t -show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83793_data *data = w83793_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - u8 mask = (index < 4) ? 0x03 : 0x01; - u8 shift = (index < 4) ? (2 * index) : (index - 4); - u8 tmp; - index = (index < 4) ? 0 : 1; - - tmp = (data->temp_mode[index] >> shift) & mask; - - /* for the internal sensor, found out if diode or thermistor */ - if (tmp == 1) - tmp = index == 0 ? 3 : 4; - else - tmp = TO_TEMP_MODE[tmp]; - - return sprintf(buf, "%d\n", tmp); -} - -static ssize_t -store_temp_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - u8 mask = (index < 4) ? 0x03 : 0x01; - u8 shift = (index < 4) ? (2 * index) : (index - 4); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - /* transform the sysfs interface values into table above */ - if ((val == 6) && (index < 4)) { - val -= 3; - } else if ((val == 3 && index < 4) - || (val == 4 && index >= 4)) { - /* transform diode or thermistor into internal enable */ - val = !!val; - } else { - return -EINVAL; - } - - index = (index < 4) ? 0 : 1; - mutex_lock(&data->update_lock); - data->temp_mode[index] = - w83793_read_value(client, W83793_REG_TEMP_MODE[index]); - data->temp_mode[index] &= ~(mask << shift); - data->temp_mode[index] |= val << shift; - w83793_write_value(client, W83793_REG_TEMP_MODE[index], - data->temp_mode[index]); - mutex_unlock(&data->update_lock); - - return count; -} - -#define SETUP_PWM_DEFAULT 0 -#define SETUP_PWM_UPTIME 1 /* Unit in 0.1s */ -#define SETUP_PWM_DOWNTIME 2 /* Unit in 0.1s */ -#define SETUP_TEMP_CRITICAL 3 -static ssize_t -show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - struct w83793_data *data = w83793_update_device(dev); - u32 val = 0; - - if (nr == SETUP_PWM_DEFAULT) - val = (data->pwm_default & 0x3f) << 2; - else if (nr == SETUP_PWM_UPTIME) - val = TIME_FROM_REG(data->pwm_uptime); - else if (nr == SETUP_PWM_DOWNTIME) - val = TIME_FROM_REG(data->pwm_downtime); - else if (nr == SETUP_TEMP_CRITICAL) - val = TEMP_FROM_REG(data->temp_critical & 0x7f); - - return sprintf(buf, "%d\n", val); -} - -static ssize_t -store_sf_setup(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (nr == SETUP_PWM_DEFAULT) { - data->pwm_default = - w83793_read_value(client, W83793_REG_PWM_DEFAULT) & 0xc0; - data->pwm_default |= SENSORS_LIMIT(val, 0, 0xff) >> 2; - w83793_write_value(client, W83793_REG_PWM_DEFAULT, - data->pwm_default); - } else if (nr == SETUP_PWM_UPTIME) { - data->pwm_uptime = TIME_TO_REG(val); - data->pwm_uptime += data->pwm_uptime == 0 ? 1 : 0; - w83793_write_value(client, W83793_REG_PWM_UPTIME, - data->pwm_uptime); - } else if (nr == SETUP_PWM_DOWNTIME) { - data->pwm_downtime = TIME_TO_REG(val); - data->pwm_downtime += data->pwm_downtime == 0 ? 1 : 0; - w83793_write_value(client, W83793_REG_PWM_DOWNTIME, - data->pwm_downtime); - } else { /* SETUP_TEMP_CRITICAL */ - data->temp_critical = - w83793_read_value(client, W83793_REG_TEMP_CRITICAL) & 0x80; - data->temp_critical |= TEMP_TO_REG(val, 0, 0x7f); - w83793_write_value(client, W83793_REG_TEMP_CRITICAL, - data->temp_critical); - } - - mutex_unlock(&data->update_lock); - return count; -} - -/* - * Temp SmartFan control - * TEMP_FAN_MAP - * Temp channel control which pwm fan, bitfield, bit 0 indicate pwm1... - * It's possible two or more temp channels control the same fan, w83793 - * always prefers to pick the most critical request and applies it to - * the related Fan. - * It's possible one fan is not in any mapping of 6 temp channels, this - * means the fan is manual mode - * - * TEMP_PWM_ENABLE - * Each temp channel has its own SmartFan mode, and temp channel - * control fans that are set by TEMP_FAN_MAP - * 0: SmartFanII mode - * 1: Thermal Cruise Mode - * - * TEMP_CRUISE - * Target temperature in thermal cruise mode, w83793 will try to turn - * fan speed to keep the temperature of target device around this - * temperature. - * - * TEMP_TOLERANCE - * If Temp higher or lower than target with this tolerance, w83793 - * will take actions to speed up or slow down the fan to keep the - * temperature within the tolerance range. - */ - -#define TEMP_FAN_MAP 0 -#define TEMP_PWM_ENABLE 1 -#define TEMP_CRUISE 2 -#define TEMP_TOLERANCE 3 -static ssize_t -show_sf_ctrl(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83793_data *data = w83793_update_device(dev); - u32 val; - - if (nr == TEMP_FAN_MAP) { - val = data->temp_fan_map[index]; - } else if (nr == TEMP_PWM_ENABLE) { - /* +2 to transfrom into 2 and 3 to conform with sysfs intf */ - val = ((data->pwm_enable >> index) & 0x01) + 2; - } else if (nr == TEMP_CRUISE) { - val = TEMP_FROM_REG(data->temp_cruise[index] & 0x7f); - } else { /* TEMP_TOLERANCE */ - val = data->tolerance[index >> 1] >> ((index & 0x01) ? 4 : 0); - val = TEMP_FROM_REG(val & 0x0f); - } - return sprintf(buf, "%d\n", val); -} - -static ssize_t -store_sf_ctrl(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - if (nr == TEMP_FAN_MAP) { - val = SENSORS_LIMIT(val, 0, 255); - w83793_write_value(client, W83793_REG_TEMP_FAN_MAP(index), val); - data->temp_fan_map[index] = val; - } else if (nr == TEMP_PWM_ENABLE) { - if (val == 2 || val == 3) { - data->pwm_enable = - w83793_read_value(client, W83793_REG_PWM_ENABLE); - if (val - 2) - data->pwm_enable |= 1 << index; - else - data->pwm_enable &= ~(1 << index); - w83793_write_value(client, W83793_REG_PWM_ENABLE, - data->pwm_enable); - } else { - mutex_unlock(&data->update_lock); - return -EINVAL; - } - } else if (nr == TEMP_CRUISE) { - data->temp_cruise[index] = - w83793_read_value(client, W83793_REG_TEMP_CRUISE(index)); - data->temp_cruise[index] &= 0x80; - data->temp_cruise[index] |= TEMP_TO_REG(val, 0, 0x7f); - - w83793_write_value(client, W83793_REG_TEMP_CRUISE(index), - data->temp_cruise[index]); - } else { /* TEMP_TOLERANCE */ - int i = index >> 1; - u8 shift = (index & 0x01) ? 4 : 0; - data->tolerance[i] = - w83793_read_value(client, W83793_REG_TEMP_TOL(i)); - - data->tolerance[i] &= ~(0x0f << shift); - data->tolerance[i] |= TEMP_TO_REG(val, 0, 0x0f) << shift; - w83793_write_value(client, W83793_REG_TEMP_TOL(i), - data->tolerance[i]); - } - - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_sf2_pwm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83793_data *data = w83793_update_device(dev); - - return sprintf(buf, "%d\n", (data->sf2_pwm[index][nr] & 0x3f) << 2); -} - -static ssize_t -store_sf2_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - val = SENSORS_LIMIT(val, 0, 0xff) >> 2; - - mutex_lock(&data->update_lock); - data->sf2_pwm[index][nr] = - w83793_read_value(client, W83793_REG_SF2_PWM(index, nr)) & 0xc0; - data->sf2_pwm[index][nr] |= val; - w83793_write_value(client, W83793_REG_SF2_PWM(index, nr), - data->sf2_pwm[index][nr]); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_sf2_temp(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83793_data *data = w83793_update_device(dev); - - return sprintf(buf, "%ld\n", - TEMP_FROM_REG(data->sf2_temp[index][nr] & 0x7f)); -} - -static ssize_t -store_sf2_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - val = TEMP_TO_REG(val, 0, 0x7f); - - mutex_lock(&data->update_lock); - data->sf2_temp[index][nr] = - w83793_read_value(client, W83793_REG_SF2_TEMP(index, nr)) & 0x80; - data->sf2_temp[index][nr] |= val; - w83793_write_value(client, W83793_REG_SF2_TEMP(index, nr), - data->sf2_temp[index][nr]); - mutex_unlock(&data->update_lock); - return count; -} - -/* only Vcore A/B and Vtt have additional 2 bits precision */ -static ssize_t -show_in(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83793_data *data = w83793_update_device(dev); - u16 val = data->in[index][nr]; - - if (index < 3) { - val <<= 2; - val += (data->in_low_bits[nr] >> (index * 2)) & 0x3; - } - /* voltage inputs 5VDD and 5VSB needs 150mV offset */ - val = val * scale_in[index] + scale_in_add[index]; - return sprintf(buf, "%d\n", val); -} - -static ssize_t -store_in(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - val = (val + scale_in[index] / 2) / scale_in[index]; - - mutex_lock(&data->update_lock); - if (index > 2) { - /* fix the limit values of 5VDD and 5VSB to ALARM mechanism */ - if (nr == 1 || nr == 2) - val -= scale_in_add[index] / scale_in[index]; - val = SENSORS_LIMIT(val, 0, 255); - } else { - val = SENSORS_LIMIT(val, 0, 0x3FF); - data->in_low_bits[nr] = - w83793_read_value(client, W83793_REG_IN_LOW_BITS[nr]); - data->in_low_bits[nr] &= ~(0x03 << (2 * index)); - data->in_low_bits[nr] |= (val & 0x03) << (2 * index); - w83793_write_value(client, W83793_REG_IN_LOW_BITS[nr], - data->in_low_bits[nr]); - val >>= 2; - } - data->in[index][nr] = val; - w83793_write_value(client, W83793_REG_IN[index][nr], - data->in[index][nr]); - mutex_unlock(&data->update_lock); - return count; -} - -#define NOT_USED -1 - -#define SENSOR_ATTR_IN(index) \ - SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \ - IN_READ, index), \ - SENSOR_ATTR_2(in##index##_max, S_IRUGO | S_IWUSR, show_in, \ - store_in, IN_MAX, index), \ - SENSOR_ATTR_2(in##index##_min, S_IRUGO | S_IWUSR, show_in, \ - store_in, IN_LOW, index), \ - SENSOR_ATTR_2(in##index##_alarm, S_IRUGO, show_alarm_beep, \ - NULL, ALARM_STATUS, index + ((index > 2) ? 1 : 0)), \ - SENSOR_ATTR_2(in##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, \ - index + ((index > 2) ? 1 : 0)) - -#define SENSOR_ATTR_FAN(index) \ - SENSOR_ATTR_2(fan##index##_alarm, S_IRUGO, show_alarm_beep, \ - NULL, ALARM_STATUS, index + 17), \ - SENSOR_ATTR_2(fan##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, index + 17), \ - SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \ - NULL, FAN_INPUT, index - 1), \ - SENSOR_ATTR_2(fan##index##_min, S_IWUSR | S_IRUGO, \ - show_fan, store_fan_min, FAN_MIN, index - 1) - -#define SENSOR_ATTR_PWM(index) \ - SENSOR_ATTR_2(pwm##index, S_IWUSR | S_IRUGO, show_pwm, \ - store_pwm, PWM_DUTY, index - 1), \ - SENSOR_ATTR_2(pwm##index##_nonstop, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_NONSTOP, index - 1), \ - SENSOR_ATTR_2(pwm##index##_start, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_START, index - 1), \ - SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_STOP_TIME, index - 1) - -#define SENSOR_ATTR_TEMP(index) \ - SENSOR_ATTR_2(temp##index##_type, S_IRUGO | S_IWUSR, \ - show_temp_mode, store_temp_mode, NOT_USED, index - 1), \ - SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \ - NULL, TEMP_READ, index - 1), \ - SENSOR_ATTR_2(temp##index##_max, S_IRUGO | S_IWUSR, show_temp, \ - store_temp, TEMP_CRIT, index - 1), \ - SENSOR_ATTR_2(temp##index##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp, store_temp, TEMP_CRIT_HYST, index - 1), \ - SENSOR_ATTR_2(temp##index##_warn, S_IRUGO | S_IWUSR, show_temp, \ - store_temp, TEMP_WARN, index - 1), \ - SENSOR_ATTR_2(temp##index##_warn_hyst, S_IRUGO | S_IWUSR, \ - show_temp, store_temp, TEMP_WARN_HYST, index - 1), \ - SENSOR_ATTR_2(temp##index##_alarm, S_IRUGO, \ - show_alarm_beep, NULL, ALARM_STATUS, index + 11), \ - SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, index + 11), \ - SENSOR_ATTR_2(temp##index##_auto_channels_pwm, \ - S_IRUGO | S_IWUSR, show_sf_ctrl, store_sf_ctrl, \ - TEMP_FAN_MAP, index - 1), \ - SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \ - show_sf_ctrl, store_sf_ctrl, TEMP_PWM_ENABLE, \ - index - 1), \ - SENSOR_ATTR_2(thermal_cruise##index, S_IRUGO | S_IWUSR, \ - show_sf_ctrl, store_sf_ctrl, TEMP_CRUISE, index - 1), \ - SENSOR_ATTR_2(tolerance##index, S_IRUGO | S_IWUSR, show_sf_ctrl,\ - store_sf_ctrl, TEMP_TOLERANCE, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point1_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 0, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point2_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 1, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point3_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 2, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point4_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 3, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point5_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 4, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point6_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 5, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point7_pwm, S_IRUGO | S_IWUSR, \ - show_sf2_pwm, store_sf2_pwm, 6, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point1_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 0, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point2_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 1, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point3_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 2, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point4_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 3, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point5_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 4, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point6_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 5, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point7_temp, S_IRUGO | S_IWUSR,\ - show_sf2_temp, store_sf2_temp, 6, index - 1) - -static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = { - SENSOR_ATTR_IN(0), - SENSOR_ATTR_IN(1), - SENSOR_ATTR_IN(2), - SENSOR_ATTR_IN(3), - SENSOR_ATTR_IN(4), - SENSOR_ATTR_IN(5), - SENSOR_ATTR_IN(6), - SENSOR_ATTR_IN(7), - SENSOR_ATTR_IN(8), - SENSOR_ATTR_IN(9), - SENSOR_ATTR_FAN(1), - SENSOR_ATTR_FAN(2), - SENSOR_ATTR_FAN(3), - SENSOR_ATTR_FAN(4), - SENSOR_ATTR_FAN(5), - SENSOR_ATTR_PWM(1), - SENSOR_ATTR_PWM(2), - SENSOR_ATTR_PWM(3), -}; - -static struct sensor_device_attribute_2 w83793_temp[] = { - SENSOR_ATTR_TEMP(1), - SENSOR_ATTR_TEMP(2), - SENSOR_ATTR_TEMP(3), - SENSOR_ATTR_TEMP(4), - SENSOR_ATTR_TEMP(5), - SENSOR_ATTR_TEMP(6), -}; - -/* Fan6-Fan12 */ -static struct sensor_device_attribute_2 w83793_left_fan[] = { - SENSOR_ATTR_FAN(6), - SENSOR_ATTR_FAN(7), - SENSOR_ATTR_FAN(8), - SENSOR_ATTR_FAN(9), - SENSOR_ATTR_FAN(10), - SENSOR_ATTR_FAN(11), - SENSOR_ATTR_FAN(12), -}; - -/* Pwm4-Pwm8 */ -static struct sensor_device_attribute_2 w83793_left_pwm[] = { - SENSOR_ATTR_PWM(4), - SENSOR_ATTR_PWM(5), - SENSOR_ATTR_PWM(6), - SENSOR_ATTR_PWM(7), - SENSOR_ATTR_PWM(8), -}; - -static struct sensor_device_attribute_2 w83793_vid[] = { - SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0), - SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1), -}; -static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm); - -static struct sensor_device_attribute_2 sda_single_files[] = { - SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, - store_chassis_clear_legacy, ALARM_STATUS, 30), - SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, - store_chassis_clear, ALARM_STATUS, 30), - SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable, - store_beep_enable, NOT_USED, NOT_USED), - SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_PWM_DEFAULT, NOT_USED), - SENSOR_ATTR_2(pwm_uptime, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_PWM_UPTIME, NOT_USED), - SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED), - SENSOR_ATTR_2(temp_critical, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_TEMP_CRITICAL, NOT_USED), -}; - -static void w83793_init_client(struct i2c_client *client) -{ - if (reset) - w83793_write_value(client, W83793_REG_CONFIG, 0x80); - - /* Start monitoring */ - w83793_write_value(client, W83793_REG_CONFIG, - w83793_read_value(client, W83793_REG_CONFIG) | 0x01); -} - -/* - * Watchdog routines - */ - -static int watchdog_set_timeout(struct w83793_data *data, int timeout) -{ - int ret, mtimeout; - - mtimeout = DIV_ROUND_UP(timeout, 60); - - if (mtimeout > 255) - return -EINVAL; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - data->watchdog_timeout = mtimeout; - - /* Set Timeout value (in Minutes) */ - w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT, - data->watchdog_timeout); - - ret = mtimeout * 60; - -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_get_timeout(struct w83793_data *data) -{ - int timeout; - - mutex_lock(&data->watchdog_lock); - timeout = data->watchdog_timeout * 60; - mutex_unlock(&data->watchdog_lock); - - return timeout; -} - -static int watchdog_trigger(struct w83793_data *data) -{ - int ret = 0; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - /* Set Timeout value (in Minutes) */ - w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT, - data->watchdog_timeout); - -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_enable(struct w83793_data *data) -{ - int ret = 0; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - /* Set initial timeout */ - w83793_write_value(data->client, W83793_REG_WDT_TIMEOUT, - data->watchdog_timeout); - - /* Enable Soft Watchdog */ - w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0x55); - -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_disable(struct w83793_data *data) -{ - int ret = 0; - - mutex_lock(&data->watchdog_lock); - if (!data->client) { - ret = -ENODEV; - goto leave; - } - - /* Disable Soft Watchdog */ - w83793_write_value(data->client, W83793_REG_WDT_LOCK, 0xAA); - -leave: - mutex_unlock(&data->watchdog_lock); - return ret; -} - -static int watchdog_open(struct inode *inode, struct file *filp) -{ - struct w83793_data *pos, *data = NULL; - int watchdog_is_open; - - /* - * We get called from drivers/char/misc.c with misc_mtx hold, and we - * call misc_register() from w83793_probe() with watchdog_data_mutex - * hold, as misc_register() takes the misc_mtx lock, this is a possible - * deadlock, so we use mutex_trylock here. - */ - if (!mutex_trylock(&watchdog_data_mutex)) - return -ERESTARTSYS; - list_for_each_entry(pos, &watchdog_data_list, list) { - if (pos->watchdog_miscdev.minor == iminor(inode)) { - data = pos; - break; - } - } - - /* Check, if device is already open */ - watchdog_is_open = test_and_set_bit(0, &data->watchdog_is_open); - - /* - * Increase data reference counter (if not already done). - * Note we can never not have found data, so we don't check for this - */ - if (!watchdog_is_open) - kref_get(&data->kref); - - mutex_unlock(&watchdog_data_mutex); - - /* Check, if device is already open and possibly issue error */ - if (watchdog_is_open) - return -EBUSY; - - /* Enable Soft Watchdog */ - watchdog_enable(data); - - /* Store pointer to data into filp's private data */ - filp->private_data = data; - - return nonseekable_open(inode, filp); -} - -static int watchdog_close(struct inode *inode, struct file *filp) -{ - struct w83793_data *data = filp->private_data; - - if (data->watchdog_expect_close) { - watchdog_disable(data); - data->watchdog_expect_close = 0; - } else { - watchdog_trigger(data); - dev_crit(&data->client->dev, - "unexpected close, not stopping watchdog!\n"); - } - - clear_bit(0, &data->watchdog_is_open); - - /* Decrease data reference counter */ - mutex_lock(&watchdog_data_mutex); - kref_put(&data->kref, w83793_release_resources); - mutex_unlock(&watchdog_data_mutex); - - return 0; -} - -static ssize_t watchdog_write(struct file *filp, const char __user *buf, - size_t count, loff_t *offset) -{ - ssize_t ret; - struct w83793_data *data = filp->private_data; - - if (count) { - if (!nowayout) { - size_t i; - - /* Clear it in case it was set with a previous write */ - data->watchdog_expect_close = 0; - - for (i = 0; i != count; i++) { - char c; - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - data->watchdog_expect_close = 1; - } - } - ret = watchdog_trigger(data); - if (ret < 0) - return ret; - } - return count; -} - -static long watchdog_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg) -{ - struct watchdog_info ident = { - .options = WDIOF_KEEPALIVEPING | - WDIOF_SETTIMEOUT | - WDIOF_CARDRESET, - .identity = "w83793 watchdog" - }; - - int val, ret = 0; - struct w83793_data *data = filp->private_data; - - switch (cmd) { - case WDIOC_GETSUPPORT: - if (!nowayout) - ident.options |= WDIOF_MAGICCLOSE; - if (copy_to_user((void __user *)arg, &ident, sizeof(ident))) - ret = -EFAULT; - break; - - case WDIOC_GETSTATUS: - val = data->watchdog_caused_reboot ? WDIOF_CARDRESET : 0; - ret = put_user(val, (int __user *)arg); - break; - - case WDIOC_GETBOOTSTATUS: - ret = put_user(0, (int __user *)arg); - break; - - case WDIOC_KEEPALIVE: - ret = watchdog_trigger(data); - break; - - case WDIOC_GETTIMEOUT: - val = watchdog_get_timeout(data); - ret = put_user(val, (int __user *)arg); - break; - - case WDIOC_SETTIMEOUT: - if (get_user(val, (int __user *)arg)) { - ret = -EFAULT; - break; - } - ret = watchdog_set_timeout(data, val); - if (ret > 0) - ret = put_user(ret, (int __user *)arg); - break; - - case WDIOC_SETOPTIONS: - if (get_user(val, (int __user *)arg)) { - ret = -EFAULT; - break; - } - - if (val & WDIOS_DISABLECARD) - ret = watchdog_disable(data); - else if (val & WDIOS_ENABLECARD) - ret = watchdog_enable(data); - else - ret = -EINVAL; - - break; - default: - ret = -ENOTTY; - } - return ret; -} - -static const struct file_operations watchdog_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .open = watchdog_open, - .release = watchdog_close, - .write = watchdog_write, - .unlocked_ioctl = watchdog_ioctl, -}; - -/* - * Notifier for system down - */ - -static int watchdog_notify_sys(struct notifier_block *this, unsigned long code, - void *unused) -{ - struct w83793_data *data = NULL; - - if (code == SYS_DOWN || code == SYS_HALT) { - - /* Disable each registered watchdog */ - mutex_lock(&watchdog_data_mutex); - list_for_each_entry(data, &watchdog_data_list, list) { - if (data->watchdog_miscdev.minor) - watchdog_disable(data); - } - mutex_unlock(&watchdog_data_mutex); - } - - return NOTIFY_DONE; -} - -/* - * The WDT needs to learn about soft shutdowns in order to - * turn the timebomb registers off. - */ - -static struct notifier_block watchdog_notifier = { - .notifier_call = watchdog_notify_sys, -}; - -/* - * Init / remove routines - */ - -static int w83793_remove(struct i2c_client *client) -{ - struct w83793_data *data = i2c_get_clientdata(client); - struct device *dev = &client->dev; - int i, tmp; - - /* Unregister the watchdog (if registered) */ - if (data->watchdog_miscdev.minor) { - misc_deregister(&data->watchdog_miscdev); - - if (data->watchdog_is_open) { - dev_warn(&client->dev, - "i2c client detached with watchdog open! " - "Stopping watchdog.\n"); - watchdog_disable(data); - } - - mutex_lock(&watchdog_data_mutex); - list_del(&data->list); - mutex_unlock(&watchdog_data_mutex); - - /* Tell the watchdog code the client is gone */ - mutex_lock(&data->watchdog_lock); - data->client = NULL; - mutex_unlock(&data->watchdog_lock); - } - - /* Reset Configuration Register to Disable Watch Dog Registers */ - tmp = w83793_read_value(client, W83793_REG_CONFIG); - w83793_write_value(client, W83793_REG_CONFIG, tmp & ~0x04); - - unregister_reboot_notifier(&watchdog_notifier); - - hwmon_device_unregister(data->hwmon_dev); - - for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) - device_remove_file(dev, - &w83793_sensor_attr_2[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) - device_remove_file(dev, &sda_single_files[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) - device_remove_file(dev, &w83793_vid[i].dev_attr); - device_remove_file(dev, &dev_attr_vrm); - - for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) - device_remove_file(dev, &w83793_left_fan[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) - device_remove_file(dev, &w83793_left_pwm[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) - device_remove_file(dev, &w83793_temp[i].dev_attr); - - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); - - /* Decrease data reference counter */ - mutex_lock(&watchdog_data_mutex); - kref_put(&data->kref, w83793_release_resources); - mutex_unlock(&watchdog_data_mutex); - - return 0; -} - -static int -w83793_detect_subclients(struct i2c_client *client) -{ - int i, id, err; - int address = client->addr; - u8 tmp; - struct i2c_adapter *adapter = client->adapter; - struct w83793_data *data = i2c_get_clientdata(client); - - id = i2c_adapter_id(adapter); - if (force_subclients[0] == id && force_subclients[1] == address) { - for (i = 2; i <= 3; i++) { - if (force_subclients[i] < 0x48 - || force_subclients[i] > 0x4f) { - dev_err(&client->dev, - "invalid subclient " - "address %d; must be 0x48-0x4f\n", - force_subclients[i]); - err = -EINVAL; - goto ERROR_SC_0; - } - } - w83793_write_value(client, W83793_REG_I2C_SUBADDR, - (force_subclients[2] & 0x07) | - ((force_subclients[3] & 0x07) << 4)); - } - - tmp = w83793_read_value(client, W83793_REG_I2C_SUBADDR); - if (!(tmp & 0x08)) - data->lm75[0] = i2c_new_dummy(adapter, 0x48 + (tmp & 0x7)); - if (!(tmp & 0x80)) { - if ((data->lm75[0] != NULL) - && ((tmp & 0x7) == ((tmp >> 4) & 0x7))) { - dev_err(&client->dev, - "duplicate addresses 0x%x, " - "use force_subclients\n", data->lm75[0]->addr); - err = -ENODEV; - goto ERROR_SC_1; - } - data->lm75[1] = i2c_new_dummy(adapter, - 0x48 + ((tmp >> 4) & 0x7)); - } - - return 0; - - /* Undo inits in case of errors */ - -ERROR_SC_1: - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); -ERROR_SC_0: - return err; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83793_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - u8 tmp, bank, chip_id; - struct i2c_adapter *adapter = client->adapter; - unsigned short address = client->addr; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); - - tmp = bank & 0x80 ? 0x5c : 0xa3; - /* Check Winbond vendor ID */ - if (tmp != i2c_smbus_read_byte_data(client, W83793_REG_VENDORID)) { - pr_debug("w83793: Detection failed at check vendor id\n"); - return -ENODEV; - } - - /* - * If Winbond chip, address of chip and W83793_REG_I2C_ADDR - * should match - */ - if ((bank & 0x07) == 0 - && i2c_smbus_read_byte_data(client, W83793_REG_I2C_ADDR) != - (address << 1)) { - pr_debug("w83793: Detection failed at check i2c addr\n"); - return -ENODEV; - } - - /* Determine the chip type now */ - chip_id = i2c_smbus_read_byte_data(client, W83793_REG_CHIPID); - if (chip_id != 0x7b) - return -ENODEV; - - strlcpy(info->type, "w83793", I2C_NAME_SIZE); - - return 0; -} - -static int w83793_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - const int watchdog_minors[] = { WATCHDOG_MINOR, 212, 213, 214, 215 }; - struct w83793_data *data; - int i, tmp, val, err; - int files_fan = ARRAY_SIZE(w83793_left_fan) / 7; - int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5; - int files_temp = ARRAY_SIZE(w83793_temp) / 6; - - data = kzalloc(sizeof(struct w83793_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->bank = i2c_smbus_read_byte_data(client, W83793_REG_BANKSEL); - mutex_init(&data->update_lock); - mutex_init(&data->watchdog_lock); - INIT_LIST_HEAD(&data->list); - kref_init(&data->kref); - - /* - * Store client pointer in our data struct for watchdog usage - * (where the client is found through a data ptr instead of the - * otherway around) - */ - data->client = client; - - err = w83793_detect_subclients(client); - if (err) - goto free_mem; - - /* Initialize the chip */ - w83793_init_client(client); - - /* - * Only fan 1-5 has their own input pins, - * Pwm 1-3 has their own pins - */ - data->has_fan = 0x1f; - data->has_pwm = 0x07; - tmp = w83793_read_value(client, W83793_REG_MFC); - val = w83793_read_value(client, W83793_REG_FANIN_CTRL); - - /* check the function of pins 49-56 */ - if (tmp & 0x80) { - data->has_vid |= 0x2; /* has VIDB */ - } else { - data->has_pwm |= 0x18; /* pwm 4,5 */ - if (val & 0x01) { /* fan 6 */ - data->has_fan |= 0x20; - data->has_pwm |= 0x20; - } - if (val & 0x02) { /* fan 7 */ - data->has_fan |= 0x40; - data->has_pwm |= 0x40; - } - if (!(tmp & 0x40) && (val & 0x04)) { /* fan 8 */ - data->has_fan |= 0x80; - data->has_pwm |= 0x80; - } - } - - /* check the function of pins 37-40 */ - if (!(tmp & 0x29)) - data->has_vid |= 0x1; /* has VIDA */ - if (0x08 == (tmp & 0x0c)) { - if (val & 0x08) /* fan 9 */ - data->has_fan |= 0x100; - if (val & 0x10) /* fan 10 */ - data->has_fan |= 0x200; - } - if (0x20 == (tmp & 0x30)) { - if (val & 0x20) /* fan 11 */ - data->has_fan |= 0x400; - if (val & 0x40) /* fan 12 */ - data->has_fan |= 0x800; - } - - if ((tmp & 0x01) && (val & 0x04)) { /* fan 8, second location */ - data->has_fan |= 0x80; - data->has_pwm |= 0x80; - } - - tmp = w83793_read_value(client, W83793_REG_FANIN_SEL); - if ((tmp & 0x01) && (val & 0x08)) { /* fan 9, second location */ - data->has_fan |= 0x100; - } - if ((tmp & 0x02) && (val & 0x10)) { /* fan 10, second location */ - data->has_fan |= 0x200; - } - if ((tmp & 0x04) && (val & 0x20)) { /* fan 11, second location */ - data->has_fan |= 0x400; - } - if ((tmp & 0x08) && (val & 0x40)) { /* fan 12, second location */ - data->has_fan |= 0x800; - } - - /* check the temp1-6 mode, ignore former AMDSI selected inputs */ - tmp = w83793_read_value(client, W83793_REG_TEMP_MODE[0]); - if (tmp & 0x01) - data->has_temp |= 0x01; - if (tmp & 0x04) - data->has_temp |= 0x02; - if (tmp & 0x10) - data->has_temp |= 0x04; - if (tmp & 0x40) - data->has_temp |= 0x08; - - tmp = w83793_read_value(client, W83793_REG_TEMP_MODE[1]); - if (tmp & 0x01) - data->has_temp |= 0x10; - if (tmp & 0x02) - data->has_temp |= 0x20; - - /* Register sysfs hooks */ - for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) { - err = device_create_file(dev, - &w83793_sensor_attr_2[i].dev_attr); - if (err) - goto exit_remove; - } - - for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) { - if (!(data->has_vid & (1 << i))) - continue; - err = device_create_file(dev, &w83793_vid[i].dev_attr); - if (err) - goto exit_remove; - } - if (data->has_vid) { - data->vrm = vid_which_vrm(); - err = device_create_file(dev, &dev_attr_vrm); - if (err) - goto exit_remove; - } - - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { - err = device_create_file(dev, &sda_single_files[i].dev_attr); - if (err) - goto exit_remove; - - } - - for (i = 0; i < 6; i++) { - int j; - if (!(data->has_temp & (1 << i))) - continue; - for (j = 0; j < files_temp; j++) { - err = device_create_file(dev, - &w83793_temp[(i) * files_temp - + j].dev_attr); - if (err) - goto exit_remove; - } - } - - for (i = 5; i < 12; i++) { - int j; - if (!(data->has_fan & (1 << i))) - continue; - for (j = 0; j < files_fan; j++) { - err = device_create_file(dev, - &w83793_left_fan[(i - 5) * files_fan - + j].dev_attr); - if (err) - goto exit_remove; - } - } - - for (i = 3; i < 8; i++) { - int j; - if (!(data->has_pwm & (1 << i))) - continue; - for (j = 0; j < files_pwm; j++) { - err = device_create_file(dev, - &w83793_left_pwm[(i - 3) * files_pwm - + j].dev_attr); - 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; - } - - /* Watchdog initialization */ - - /* Register boot notifier */ - err = register_reboot_notifier(&watchdog_notifier); - if (err != 0) { - dev_err(&client->dev, - "cannot register reboot notifier (err=%d)\n", err); - goto exit_devunreg; - } - - /* - * Enable Watchdog registers. - * Set Configuration Register to Enable Watch Dog Registers - * (Bit 2) = XXXX, X1XX. - */ - tmp = w83793_read_value(client, W83793_REG_CONFIG); - w83793_write_value(client, W83793_REG_CONFIG, tmp | 0x04); - - /* Set the default watchdog timeout */ - data->watchdog_timeout = timeout; - - /* Check, if last reboot was caused by watchdog */ - data->watchdog_caused_reboot = - w83793_read_value(data->client, W83793_REG_WDT_STATUS) & 0x01; - - /* Disable Soft Watchdog during initialiation */ - watchdog_disable(data); - - /* - * We take the data_mutex lock early so that watchdog_open() cannot - * run when misc_register() has completed, but we've not yet added - * our data to the watchdog_data_list (and set the default timeout) - */ - mutex_lock(&watchdog_data_mutex); - for (i = 0; i < ARRAY_SIZE(watchdog_minors); i++) { - /* Register our watchdog part */ - snprintf(data->watchdog_name, sizeof(data->watchdog_name), - "watchdog%c", (i == 0) ? '\0' : ('0' + i)); - data->watchdog_miscdev.name = data->watchdog_name; - data->watchdog_miscdev.fops = &watchdog_fops; - data->watchdog_miscdev.minor = watchdog_minors[i]; - - err = misc_register(&data->watchdog_miscdev); - if (err == -EBUSY) - continue; - if (err) { - data->watchdog_miscdev.minor = 0; - dev_err(&client->dev, - "Registering watchdog chardev: %d\n", err); - break; - } - - list_add(&data->list, &watchdog_data_list); - - dev_info(&client->dev, - "Registered watchdog chardev major 10, minor: %d\n", - watchdog_minors[i]); - break; - } - if (i == ARRAY_SIZE(watchdog_minors)) { - data->watchdog_miscdev.minor = 0; - dev_warn(&client->dev, "Couldn't register watchdog chardev " - "(due to no free minor)\n"); - } - - mutex_unlock(&watchdog_data_mutex); - - return 0; - - /* Unregister hwmon device */ - -exit_devunreg: - - hwmon_device_unregister(data->hwmon_dev); - - /* Unregister sysfs hooks */ - -exit_remove: - for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) - device_remove_file(dev, &w83793_sensor_attr_2[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) - device_remove_file(dev, &sda_single_files[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) - device_remove_file(dev, &w83793_vid[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++) - device_remove_file(dev, &w83793_left_fan[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++) - device_remove_file(dev, &w83793_left_pwm[i].dev_attr); - - for (i = 0; i < ARRAY_SIZE(w83793_temp); i++) - device_remove_file(dev, &w83793_temp[i].dev_attr); - - if (data->lm75[0] != NULL) - i2c_unregister_device(data->lm75[0]); - if (data->lm75[1] != NULL) - i2c_unregister_device(data->lm75[1]); -free_mem: - kfree(data); -exit: - return err; -} - -static void w83793_update_nonvolatile(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - int i, j; - /* - * They are somewhat "stable" registers, and to update them every time - * takes so much time, it's just not worthy. Update them in a long - * interval to avoid exception. - */ - if (!(time_after(jiffies, data->last_nonvolatile + HZ * 300) - || !data->valid)) - return; - /* update voltage limits */ - for (i = 1; i < 3; i++) { - for (j = 0; j < ARRAY_SIZE(data->in); j++) { - data->in[j][i] = - w83793_read_value(client, W83793_REG_IN[j][i]); - } - data->in_low_bits[i] = - w83793_read_value(client, W83793_REG_IN_LOW_BITS[i]); - } - - for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) { - /* Update the Fan measured value and limits */ - if (!(data->has_fan & (1 << i))) - continue; - data->fan_min[i] = - w83793_read_value(client, W83793_REG_FAN_MIN(i)) << 8; - data->fan_min[i] |= - w83793_read_value(client, W83793_REG_FAN_MIN(i) + 1); - } - - for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) { - if (!(data->has_temp & (1 << i))) - continue; - data->temp_fan_map[i] = - w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i)); - for (j = 1; j < 5; j++) { - data->temp[i][j] = - w83793_read_value(client, W83793_REG_TEMP[i][j]); - } - data->temp_cruise[i] = - w83793_read_value(client, W83793_REG_TEMP_CRUISE(i)); - for (j = 0; j < 7; j++) { - data->sf2_pwm[i][j] = - w83793_read_value(client, W83793_REG_SF2_PWM(i, j)); - data->sf2_temp[i][j] = - w83793_read_value(client, - W83793_REG_SF2_TEMP(i, j)); - } - } - - for (i = 0; i < ARRAY_SIZE(data->temp_mode); i++) - data->temp_mode[i] = - w83793_read_value(client, W83793_REG_TEMP_MODE[i]); - - for (i = 0; i < ARRAY_SIZE(data->tolerance); i++) { - data->tolerance[i] = - w83793_read_value(client, W83793_REG_TEMP_TOL(i)); - } - - for (i = 0; i < ARRAY_SIZE(data->pwm); i++) { - if (!(data->has_pwm & (1 << i))) - continue; - data->pwm[i][PWM_NONSTOP] = - w83793_read_value(client, W83793_REG_PWM(i, PWM_NONSTOP)); - data->pwm[i][PWM_START] = - w83793_read_value(client, W83793_REG_PWM(i, PWM_START)); - data->pwm_stop_time[i] = - w83793_read_value(client, W83793_REG_PWM_STOP_TIME(i)); - } - - data->pwm_default = w83793_read_value(client, W83793_REG_PWM_DEFAULT); - data->pwm_enable = w83793_read_value(client, W83793_REG_PWM_ENABLE); - data->pwm_uptime = w83793_read_value(client, W83793_REG_PWM_UPTIME); - data->pwm_downtime = w83793_read_value(client, W83793_REG_PWM_DOWNTIME); - data->temp_critical = - w83793_read_value(client, W83793_REG_TEMP_CRITICAL); - data->beep_enable = w83793_read_value(client, W83793_REG_OVT_BEEP); - - for (i = 0; i < ARRAY_SIZE(data->beeps); i++) - data->beeps[i] = w83793_read_value(client, W83793_REG_BEEP(i)); - - data->last_nonvolatile = jiffies; -} - -static struct w83793_data *w83793_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (!(time_after(jiffies, data->last_updated + HZ * 2) - || !data->valid)) - goto END; - - /* Update the voltages measured value and limits */ - for (i = 0; i < ARRAY_SIZE(data->in); i++) - data->in[i][IN_READ] = - w83793_read_value(client, W83793_REG_IN[i][IN_READ]); - - data->in_low_bits[IN_READ] = - w83793_read_value(client, W83793_REG_IN_LOW_BITS[IN_READ]); - - for (i = 0; i < ARRAY_SIZE(data->fan); i++) { - if (!(data->has_fan & (1 << i))) - continue; - data->fan[i] = - w83793_read_value(client, W83793_REG_FAN(i)) << 8; - data->fan[i] |= - w83793_read_value(client, W83793_REG_FAN(i) + 1); - } - - for (i = 0; i < ARRAY_SIZE(data->temp); i++) { - if (!(data->has_temp & (1 << i))) - continue; - data->temp[i][TEMP_READ] = - w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]); - } - - data->temp_low_bits = - w83793_read_value(client, W83793_REG_TEMP_LOW_BITS); - - for (i = 0; i < ARRAY_SIZE(data->pwm); i++) { - if (data->has_pwm & (1 << i)) - data->pwm[i][PWM_DUTY] = - w83793_read_value(client, - W83793_REG_PWM(i, PWM_DUTY)); - } - - for (i = 0; i < ARRAY_SIZE(data->alarms); i++) - data->alarms[i] = - w83793_read_value(client, W83793_REG_ALARM(i)); - if (data->has_vid & 0x01) - data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA); - if (data->has_vid & 0x02) - data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB); - w83793_update_nonvolatile(dev); - data->last_updated = jiffies; - data->valid = 1; - -END: - mutex_unlock(&data->update_lock); - return data; -} - -/* - * Ignore the possibility that somebody change bank outside the driver - * Must be called with data->update_lock held, except during initialization - */ -static u8 w83793_read_value(struct i2c_client *client, u16 reg) -{ - struct w83793_data *data = i2c_get_clientdata(client); - u8 res = 0xff; - u8 new_bank = reg >> 8; - - new_bank |= data->bank & 0xfc; - if (data->bank != new_bank) { - if (i2c_smbus_write_byte_data - (client, W83793_REG_BANKSEL, new_bank) >= 0) - data->bank = new_bank; - else { - dev_err(&client->dev, - "set bank to %d failed, fall back " - "to bank %d, read reg 0x%x error\n", - new_bank, data->bank, reg); - res = 0x0; /* read 0x0 from the chip */ - goto END; - } - } - res = i2c_smbus_read_byte_data(client, reg & 0xff); -END: - return res; -} - -/* Must be called with data->update_lock held, except during initialization */ -static int w83793_write_value(struct i2c_client *client, u16 reg, u8 value) -{ - struct w83793_data *data = i2c_get_clientdata(client); - int res; - u8 new_bank = reg >> 8; - - new_bank |= data->bank & 0xfc; - if (data->bank != new_bank) { - res = i2c_smbus_write_byte_data(client, W83793_REG_BANKSEL, - new_bank); - if (res < 0) { - dev_err(&client->dev, - "set bank to %d failed, fall back " - "to bank %d, write reg 0x%x error\n", - new_bank, data->bank, reg); - goto END; - } - data->bank = new_bank; - } - - res = i2c_smbus_write_byte_data(client, reg & 0xff, value); -END: - return res; -} - -module_i2c_driver(w83793_driver); - -MODULE_AUTHOR("Yuan Mu, Sven Anders"); -MODULE_DESCRIPTION("w83793 driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83795.c b/ANDROID_3.4.5/drivers/hwmon/w83795.c deleted file mode 100644 index d887cb3b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83795.c +++ /dev/null @@ -1,2291 +0,0 @@ -/* - * w83795.c - Linux kernel driver for hardware monitoring - * Copyright (C) 2008 Nuvoton Technology Corp. - * Wei Song - * Copyright (C) 2010 Jean Delvare - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation - version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - * - * Supports following chips: - * - * Chip #vin #fanin #pwm #temp #dts wchipid vendid i2c ISA - * w83795g 21 14 8 6 8 0x79 0x5ca3 yes no - * w83795adg 18 14 2 6 8 0x79 0x5ca3 yes no - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { - 0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END -}; - - -static bool reset; -module_param(reset, bool, 0); -MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); - - -#define W83795_REG_BANKSEL 0x00 -#define W83795_REG_VENDORID 0xfd -#define W83795_REG_CHIPID 0xfe -#define W83795_REG_DEVICEID 0xfb -#define W83795_REG_DEVICEID_A 0xff - -#define W83795_REG_I2C_ADDR 0xfc -#define W83795_REG_CONFIG 0x01 -#define W83795_REG_CONFIG_CONFIG48 0x04 -#define W83795_REG_CONFIG_START 0x01 - -/* Multi-Function Pin Ctrl Registers */ -#define W83795_REG_VOLT_CTRL1 0x02 -#define W83795_REG_VOLT_CTRL2 0x03 -#define W83795_REG_TEMP_CTRL1 0x04 -#define W83795_REG_TEMP_CTRL2 0x05 -#define W83795_REG_FANIN_CTRL1 0x06 -#define W83795_REG_FANIN_CTRL2 0x07 -#define W83795_REG_VMIGB_CTRL 0x08 - -#define TEMP_READ 0 -#define TEMP_CRIT 1 -#define TEMP_CRIT_HYST 2 -#define TEMP_WARN 3 -#define TEMP_WARN_HYST 4 -/* - * only crit and crit_hyst affect real-time alarm status - * current crit crit_hyst warn warn_hyst - */ -static const u16 W83795_REG_TEMP[][5] = { - {0x21, 0x96, 0x97, 0x98, 0x99}, /* TD1/TR1 */ - {0x22, 0x9a, 0x9b, 0x9c, 0x9d}, /* TD2/TR2 */ - {0x23, 0x9e, 0x9f, 0xa0, 0xa1}, /* TD3/TR3 */ - {0x24, 0xa2, 0xa3, 0xa4, 0xa5}, /* TD4/TR4 */ - {0x1f, 0xa6, 0xa7, 0xa8, 0xa9}, /* TR5 */ - {0x20, 0xaa, 0xab, 0xac, 0xad}, /* TR6 */ -}; - -#define IN_READ 0 -#define IN_MAX 1 -#define IN_LOW 2 -static const u16 W83795_REG_IN[][3] = { - /* Current, HL, LL */ - {0x10, 0x70, 0x71}, /* VSEN1 */ - {0x11, 0x72, 0x73}, /* VSEN2 */ - {0x12, 0x74, 0x75}, /* VSEN3 */ - {0x13, 0x76, 0x77}, /* VSEN4 */ - {0x14, 0x78, 0x79}, /* VSEN5 */ - {0x15, 0x7a, 0x7b}, /* VSEN6 */ - {0x16, 0x7c, 0x7d}, /* VSEN7 */ - {0x17, 0x7e, 0x7f}, /* VSEN8 */ - {0x18, 0x80, 0x81}, /* VSEN9 */ - {0x19, 0x82, 0x83}, /* VSEN10 */ - {0x1A, 0x84, 0x85}, /* VSEN11 */ - {0x1B, 0x86, 0x87}, /* VTT */ - {0x1C, 0x88, 0x89}, /* 3VDD */ - {0x1D, 0x8a, 0x8b}, /* 3VSB */ - {0x1E, 0x8c, 0x8d}, /* VBAT */ - {0x1F, 0xa6, 0xa7}, /* VSEN12 */ - {0x20, 0xaa, 0xab}, /* VSEN13 */ - {0x21, 0x96, 0x97}, /* VSEN14 */ - {0x22, 0x9a, 0x9b}, /* VSEN15 */ - {0x23, 0x9e, 0x9f}, /* VSEN16 */ - {0x24, 0xa2, 0xa3}, /* VSEN17 */ -}; -#define W83795_REG_VRLSB 0x3C - -static const u8 W83795_REG_IN_HL_LSB[] = { - 0x8e, /* VSEN1-4 */ - 0x90, /* VSEN5-8 */ - 0x92, /* VSEN9-11 */ - 0x94, /* VTT, 3VDD, 3VSB, 3VBAT */ - 0xa8, /* VSEN12 */ - 0xac, /* VSEN13 */ - 0x98, /* VSEN14 */ - 0x9c, /* VSEN15 */ - 0xa0, /* VSEN16 */ - 0xa4, /* VSEN17 */ -}; - -#define IN_LSB_REG(index, type) \ - (((type) == 1) ? W83795_REG_IN_HL_LSB[(index)] \ - : (W83795_REG_IN_HL_LSB[(index)] + 1)) - -#define IN_LSB_SHIFT 0 -#define IN_LSB_IDX 1 -static const u8 IN_LSB_SHIFT_IDX[][2] = { - /* High/Low LSB shift, LSB No. */ - {0x00, 0x00}, /* VSEN1 */ - {0x02, 0x00}, /* VSEN2 */ - {0x04, 0x00}, /* VSEN3 */ - {0x06, 0x00}, /* VSEN4 */ - {0x00, 0x01}, /* VSEN5 */ - {0x02, 0x01}, /* VSEN6 */ - {0x04, 0x01}, /* VSEN7 */ - {0x06, 0x01}, /* VSEN8 */ - {0x00, 0x02}, /* VSEN9 */ - {0x02, 0x02}, /* VSEN10 */ - {0x04, 0x02}, /* VSEN11 */ - {0x00, 0x03}, /* VTT */ - {0x02, 0x03}, /* 3VDD */ - {0x04, 0x03}, /* 3VSB */ - {0x06, 0x03}, /* VBAT */ - {0x06, 0x04}, /* VSEN12 */ - {0x06, 0x05}, /* VSEN13 */ - {0x06, 0x06}, /* VSEN14 */ - {0x06, 0x07}, /* VSEN15 */ - {0x06, 0x08}, /* VSEN16 */ - {0x06, 0x09}, /* VSEN17 */ -}; - - -#define W83795_REG_FAN(index) (0x2E + (index)) -#define W83795_REG_FAN_MIN_HL(index) (0xB6 + (index)) -#define W83795_REG_FAN_MIN_LSB(index) (0xC4 + (index) / 2) -#define W83795_REG_FAN_MIN_LSB_SHIFT(index) \ - (((index) & 1) ? 4 : 0) - -#define W83795_REG_VID_CTRL 0x6A - -#define W83795_REG_ALARM_CTRL 0x40 -#define ALARM_CTRL_RTSACS (1 << 7) -#define W83795_REG_ALARM(index) (0x41 + (index)) -#define W83795_REG_CLR_CHASSIS 0x4D -#define W83795_REG_BEEP(index) (0x50 + (index)) - -#define W83795_REG_OVT_CFG 0x58 -#define OVT_CFG_SEL (1 << 7) - - -#define W83795_REG_FCMS1 0x201 -#define W83795_REG_FCMS2 0x208 -#define W83795_REG_TFMR(index) (0x202 + (index)) -#define W83795_REG_FOMC 0x20F - -#define W83795_REG_TSS(index) (0x209 + (index)) - -#define TSS_MAP_RESERVED 0xff -static const u8 tss_map[4][6] = { - { 0, 1, 2, 3, 4, 5}, - { 6, 7, 8, 9, 0, 1}, - {10, 11, 12, 13, 2, 3}, - { 4, 5, 4, 5, TSS_MAP_RESERVED, TSS_MAP_RESERVED}, -}; - -#define PWM_OUTPUT 0 -#define PWM_FREQ 1 -#define PWM_START 2 -#define PWM_NONSTOP 3 -#define PWM_STOP_TIME 4 -#define W83795_REG_PWM(index, nr) (0x210 + (nr) * 8 + (index)) - -#define W83795_REG_FTSH(index) (0x240 + (index) * 2) -#define W83795_REG_FTSL(index) (0x241 + (index) * 2) -#define W83795_REG_TFTS 0x250 - -#define TEMP_PWM_TTTI 0 -#define TEMP_PWM_CTFS 1 -#define TEMP_PWM_HCT 2 -#define TEMP_PWM_HOT 3 -#define W83795_REG_TTTI(index) (0x260 + (index)) -#define W83795_REG_CTFS(index) (0x268 + (index)) -#define W83795_REG_HT(index) (0x270 + (index)) - -#define SF4_TEMP 0 -#define SF4_PWM 1 -#define W83795_REG_SF4_TEMP(temp_num, index) \ - (0x280 + 0x10 * (temp_num) + (index)) -#define W83795_REG_SF4_PWM(temp_num, index) \ - (0x288 + 0x10 * (temp_num) + (index)) - -#define W83795_REG_DTSC 0x301 -#define W83795_REG_DTSE 0x302 -#define W83795_REG_DTS(index) (0x26 + (index)) -#define W83795_REG_PECI_TBASE(index) (0x320 + (index)) - -#define DTS_CRIT 0 -#define DTS_CRIT_HYST 1 -#define DTS_WARN 2 -#define DTS_WARN_HYST 3 -#define W83795_REG_DTS_EXT(index) (0xB2 + (index)) - -#define SETUP_PWM_DEFAULT 0 -#define SETUP_PWM_UPTIME 1 -#define SETUP_PWM_DOWNTIME 2 -#define W83795_REG_SETUP_PWM(index) (0x20C + (index)) - -static inline u16 in_from_reg(u8 index, u16 val) -{ - /* 3VDD, 3VSB and VBAT: 6 mV/bit; other inputs: 2 mV/bit */ - if (index >= 12 && index <= 14) - return val * 6; - else - return val * 2; -} - -static inline u16 in_to_reg(u8 index, u16 val) -{ - if (index >= 12 && index <= 14) - return val / 6; - else - return val / 2; -} - -static inline unsigned long fan_from_reg(u16 val) -{ - if ((val == 0xfff) || (val == 0)) - return 0; - return 1350000UL / val; -} - -static inline u16 fan_to_reg(long rpm) -{ - if (rpm <= 0) - return 0x0fff; - return SENSORS_LIMIT((1350000 + (rpm >> 1)) / rpm, 1, 0xffe); -} - -static inline unsigned long time_from_reg(u8 reg) -{ - return reg * 100; -} - -static inline u8 time_to_reg(unsigned long val) -{ - return SENSORS_LIMIT((val + 50) / 100, 0, 0xff); -} - -static inline long temp_from_reg(s8 reg) -{ - return reg * 1000; -} - -static inline s8 temp_to_reg(long val, s8 min, s8 max) -{ - return SENSORS_LIMIT(val / 1000, min, max); -} - -static const u16 pwm_freq_cksel0[16] = { - 1024, 512, 341, 256, 205, 171, 146, 128, - 85, 64, 32, 16, 8, 4, 2, 1 -}; - -static unsigned int pwm_freq_from_reg(u8 reg, u16 clkin) -{ - unsigned long base_clock; - - if (reg & 0x80) { - base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256); - return base_clock / ((reg & 0x7f) + 1); - } else - return pwm_freq_cksel0[reg & 0x0f]; -} - -static u8 pwm_freq_to_reg(unsigned long val, u16 clkin) -{ - unsigned long base_clock; - u8 reg0, reg1; - unsigned long best0, best1; - - /* Best fit for cksel = 0 */ - for (reg0 = 0; reg0 < ARRAY_SIZE(pwm_freq_cksel0) - 1; reg0++) { - if (val > (pwm_freq_cksel0[reg0] + - pwm_freq_cksel0[reg0 + 1]) / 2) - break; - } - if (val < 375) /* cksel = 1 can't beat this */ - return reg0; - best0 = pwm_freq_cksel0[reg0]; - - /* Best fit for cksel = 1 */ - base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256); - reg1 = SENSORS_LIMIT(DIV_ROUND_CLOSEST(base_clock, val), 1, 128); - best1 = base_clock / reg1; - reg1 = 0x80 | (reg1 - 1); - - /* Choose the closest one */ - if (abs(val - best0) > abs(val - best1)) - return reg1; - else - return reg0; -} - -enum chip_types {w83795g, w83795adg}; - -struct w83795_data { - struct device *hwmon_dev; - struct mutex update_lock; - unsigned long last_updated; /* In jiffies */ - enum chip_types chip_type; - - u8 bank; - - u32 has_in; /* Enable monitor VIN or not */ - u8 has_dyn_in; /* Only in2-0 can have this */ - u16 in[21][3]; /* Register value, read/high/low */ - u8 in_lsb[10][3]; /* LSB Register value, high/low */ - u8 has_gain; /* has gain: in17-20 * 8 */ - - u16 has_fan; /* Enable fan14-1 or not */ - u16 fan[14]; /* Register value combine */ - u16 fan_min[14]; /* Register value combine */ - - u8 has_temp; /* Enable monitor temp6-1 or not */ - s8 temp[6][5]; /* current, crit, crit_hyst, warn, warn_hyst */ - u8 temp_read_vrlsb[6]; - u8 temp_mode; /* Bit vector, 0 = TR, 1 = TD */ - u8 temp_src[3]; /* Register value */ - - u8 enable_dts; /* - * Enable PECI and SB-TSI, - * bit 0: =1 enable, =0 disable, - * bit 1: =1 AMD SB-TSI, =0 Intel PECI - */ - u8 has_dts; /* Enable monitor DTS temp */ - s8 dts[8]; /* Register value */ - u8 dts_read_vrlsb[8]; /* Register value */ - s8 dts_ext[4]; /* Register value */ - - u8 has_pwm; /* - * 795g supports 8 pwm, 795adg only supports 2, - * no config register, only affected by chip - * type - */ - u8 pwm[8][5]; /* - * Register value, output, freq, start, - * non stop, stop time - */ - u16 clkin; /* CLKIN frequency in kHz */ - u8 pwm_fcms[2]; /* Register value */ - u8 pwm_tfmr[6]; /* Register value */ - u8 pwm_fomc; /* Register value */ - - u16 target_speed[8]; /* - * Register value, target speed for speed - * cruise - */ - u8 tol_speed; /* tolerance of target speed */ - u8 pwm_temp[6][4]; /* TTTI, CTFS, HCT, HOT */ - u8 sf4_reg[6][2][7]; /* 6 temp, temp/dcpwm, 7 registers */ - - u8 setup_pwm[3]; /* Register value */ - - u8 alarms[6]; /* Register value */ - u8 enable_beep; - u8 beeps[6]; /* Register value */ - - char valid; - char valid_limits; - char valid_pwm_config; -}; - -/* - * Hardware access - * We assume that nobdody can change the bank outside the driver. - */ - -/* Must be called with data->update_lock held, except during initialization */ -static int w83795_set_bank(struct i2c_client *client, u8 bank) -{ - struct w83795_data *data = i2c_get_clientdata(client); - int err; - - /* If the same bank is already set, nothing to do */ - if ((data->bank & 0x07) == bank) - return 0; - - /* Change to new bank, preserve all other bits */ - bank |= data->bank & ~0x07; - err = i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL, bank); - if (err < 0) { - dev_err(&client->dev, - "Failed to set bank to %d, err %d\n", - (int)bank, err); - return err; - } - data->bank = bank; - - return 0; -} - -/* Must be called with data->update_lock held, except during initialization */ -static u8 w83795_read(struct i2c_client *client, u16 reg) -{ - int err; - - err = w83795_set_bank(client, reg >> 8); - if (err < 0) - return 0x00; /* Arbitrary */ - - err = i2c_smbus_read_byte_data(client, reg & 0xff); - if (err < 0) { - dev_err(&client->dev, - "Failed to read from register 0x%03x, err %d\n", - (int)reg, err); - return 0x00; /* Arbitrary */ - } - return err; -} - -/* Must be called with data->update_lock held, except during initialization */ -static int w83795_write(struct i2c_client *client, u16 reg, u8 value) -{ - int err; - - err = w83795_set_bank(client, reg >> 8); - if (err < 0) - return err; - - err = i2c_smbus_write_byte_data(client, reg & 0xff, value); - if (err < 0) - dev_err(&client->dev, - "Failed to write to register 0x%03x, err %d\n", - (int)reg, err); - return err; -} - -static void w83795_update_limits(struct i2c_client *client) -{ - struct w83795_data *data = i2c_get_clientdata(client); - int i, limit; - u8 lsb; - - /* Read the voltage limits */ - for (i = 0; i < ARRAY_SIZE(data->in); i++) { - if (!(data->has_in & (1 << i))) - continue; - data->in[i][IN_MAX] = - w83795_read(client, W83795_REG_IN[i][IN_MAX]); - data->in[i][IN_LOW] = - w83795_read(client, W83795_REG_IN[i][IN_LOW]); - } - for (i = 0; i < ARRAY_SIZE(data->in_lsb); i++) { - if ((i == 2 && data->chip_type == w83795adg) || - (i >= 4 && !(data->has_in & (1 << (i + 11))))) - continue; - data->in_lsb[i][IN_MAX] = - w83795_read(client, IN_LSB_REG(i, IN_MAX)); - data->in_lsb[i][IN_LOW] = - w83795_read(client, IN_LSB_REG(i, IN_LOW)); - } - - /* Read the fan limits */ - lsb = 0; /* Silent false gcc warning */ - for (i = 0; i < ARRAY_SIZE(data->fan); i++) { - /* - * Each register contains LSB for 2 fans, but we want to - * read it only once to save time - */ - if ((i & 1) == 0 && (data->has_fan & (3 << i))) - lsb = w83795_read(client, W83795_REG_FAN_MIN_LSB(i)); - - if (!(data->has_fan & (1 << i))) - continue; - data->fan_min[i] = - w83795_read(client, W83795_REG_FAN_MIN_HL(i)) << 4; - data->fan_min[i] |= - (lsb >> W83795_REG_FAN_MIN_LSB_SHIFT(i)) & 0x0F; - } - - /* Read the temperature limits */ - for (i = 0; i < ARRAY_SIZE(data->temp); i++) { - if (!(data->has_temp & (1 << i))) - continue; - for (limit = TEMP_CRIT; limit <= TEMP_WARN_HYST; limit++) - data->temp[i][limit] = - w83795_read(client, W83795_REG_TEMP[i][limit]); - } - - /* Read the DTS limits */ - if (data->enable_dts) { - for (limit = DTS_CRIT; limit <= DTS_WARN_HYST; limit++) - data->dts_ext[limit] = - w83795_read(client, W83795_REG_DTS_EXT(limit)); - } - - /* Read beep settings */ - if (data->enable_beep) { - for (i = 0; i < ARRAY_SIZE(data->beeps); i++) - data->beeps[i] = - w83795_read(client, W83795_REG_BEEP(i)); - } - - data->valid_limits = 1; -} - -static struct w83795_data *w83795_update_pwm_config(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - int i, tmp; - - mutex_lock(&data->update_lock); - - if (data->valid_pwm_config) - goto END; - - /* Read temperature source selection */ - for (i = 0; i < ARRAY_SIZE(data->temp_src); i++) - data->temp_src[i] = w83795_read(client, W83795_REG_TSS(i)); - - /* Read automatic fan speed control settings */ - data->pwm_fcms[0] = w83795_read(client, W83795_REG_FCMS1); - data->pwm_fcms[1] = w83795_read(client, W83795_REG_FCMS2); - for (i = 0; i < ARRAY_SIZE(data->pwm_tfmr); i++) - data->pwm_tfmr[i] = w83795_read(client, W83795_REG_TFMR(i)); - data->pwm_fomc = w83795_read(client, W83795_REG_FOMC); - for (i = 0; i < data->has_pwm; i++) { - for (tmp = PWM_FREQ; tmp <= PWM_STOP_TIME; tmp++) - data->pwm[i][tmp] = - w83795_read(client, W83795_REG_PWM(i, tmp)); - } - for (i = 0; i < ARRAY_SIZE(data->target_speed); i++) { - data->target_speed[i] = - w83795_read(client, W83795_REG_FTSH(i)) << 4; - data->target_speed[i] |= - w83795_read(client, W83795_REG_FTSL(i)) >> 4; - } - data->tol_speed = w83795_read(client, W83795_REG_TFTS) & 0x3f; - - for (i = 0; i < ARRAY_SIZE(data->pwm_temp); i++) { - data->pwm_temp[i][TEMP_PWM_TTTI] = - w83795_read(client, W83795_REG_TTTI(i)) & 0x7f; - data->pwm_temp[i][TEMP_PWM_CTFS] = - w83795_read(client, W83795_REG_CTFS(i)); - tmp = w83795_read(client, W83795_REG_HT(i)); - data->pwm_temp[i][TEMP_PWM_HCT] = tmp >> 4; - data->pwm_temp[i][TEMP_PWM_HOT] = tmp & 0x0f; - } - - /* Read SmartFanIV trip points */ - for (i = 0; i < ARRAY_SIZE(data->sf4_reg); i++) { - for (tmp = 0; tmp < 7; tmp++) { - data->sf4_reg[i][SF4_TEMP][tmp] = - w83795_read(client, - W83795_REG_SF4_TEMP(i, tmp)); - data->sf4_reg[i][SF4_PWM][tmp] = - w83795_read(client, W83795_REG_SF4_PWM(i, tmp)); - } - } - - /* Read setup PWM */ - for (i = 0; i < ARRAY_SIZE(data->setup_pwm); i++) - data->setup_pwm[i] = - w83795_read(client, W83795_REG_SETUP_PWM(i)); - - data->valid_pwm_config = 1; - -END: - mutex_unlock(&data->update_lock); - return data; -} - -static struct w83795_data *w83795_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - u16 tmp; - u8 intrusion; - int i; - - mutex_lock(&data->update_lock); - - if (!data->valid_limits) - w83795_update_limits(client); - - if (!(time_after(jiffies, data->last_updated + HZ * 2) - || !data->valid)) - goto END; - - /* Update the voltages value */ - for (i = 0; i < ARRAY_SIZE(data->in); i++) { - if (!(data->has_in & (1 << i))) - continue; - tmp = w83795_read(client, W83795_REG_IN[i][IN_READ]) << 2; - tmp |= w83795_read(client, W83795_REG_VRLSB) >> 6; - data->in[i][IN_READ] = tmp; - } - - /* in0-2 can have dynamic limits (W83795G only) */ - if (data->has_dyn_in) { - u8 lsb_max = w83795_read(client, IN_LSB_REG(0, IN_MAX)); - u8 lsb_low = w83795_read(client, IN_LSB_REG(0, IN_LOW)); - - for (i = 0; i < 3; i++) { - if (!(data->has_dyn_in & (1 << i))) - continue; - data->in[i][IN_MAX] = - w83795_read(client, W83795_REG_IN[i][IN_MAX]); - data->in[i][IN_LOW] = - w83795_read(client, W83795_REG_IN[i][IN_LOW]); - data->in_lsb[i][IN_MAX] = (lsb_max >> (2 * i)) & 0x03; - data->in_lsb[i][IN_LOW] = (lsb_low >> (2 * i)) & 0x03; - } - } - - /* Update fan */ - for (i = 0; i < ARRAY_SIZE(data->fan); i++) { - if (!(data->has_fan & (1 << i))) - continue; - data->fan[i] = w83795_read(client, W83795_REG_FAN(i)) << 4; - data->fan[i] |= w83795_read(client, W83795_REG_VRLSB) >> 4; - } - - /* Update temperature */ - for (i = 0; i < ARRAY_SIZE(data->temp); i++) { - data->temp[i][TEMP_READ] = - w83795_read(client, W83795_REG_TEMP[i][TEMP_READ]); - data->temp_read_vrlsb[i] = - w83795_read(client, W83795_REG_VRLSB); - } - - /* Update dts temperature */ - if (data->enable_dts) { - for (i = 0; i < ARRAY_SIZE(data->dts); i++) { - if (!(data->has_dts & (1 << i))) - continue; - data->dts[i] = - w83795_read(client, W83795_REG_DTS(i)); - data->dts_read_vrlsb[i] = - w83795_read(client, W83795_REG_VRLSB); - } - } - - /* Update pwm output */ - for (i = 0; i < data->has_pwm; i++) { - data->pwm[i][PWM_OUTPUT] = - w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT)); - } - - /* - * Update intrusion and alarms - * It is important to read intrusion first, because reading from - * register SMI STS6 clears the interrupt status temporarily. - */ - tmp = w83795_read(client, W83795_REG_ALARM_CTRL); - /* Switch to interrupt status for intrusion if needed */ - if (tmp & ALARM_CTRL_RTSACS) - w83795_write(client, W83795_REG_ALARM_CTRL, - tmp & ~ALARM_CTRL_RTSACS); - intrusion = w83795_read(client, W83795_REG_ALARM(5)) & (1 << 6); - /* Switch to real-time alarms */ - w83795_write(client, W83795_REG_ALARM_CTRL, tmp | ALARM_CTRL_RTSACS); - for (i = 0; i < ARRAY_SIZE(data->alarms); i++) - data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i)); - data->alarms[5] |= intrusion; - /* Restore original configuration if needed */ - if (!(tmp & ALARM_CTRL_RTSACS)) - w83795_write(client, W83795_REG_ALARM_CTRL, - tmp & ~ALARM_CTRL_RTSACS); - - data->last_updated = jiffies; - data->valid = 1; - -END: - mutex_unlock(&data->update_lock); - return data; -} - -/* - * Sysfs attributes - */ - -#define ALARM_STATUS 0 -#define BEEP_ENABLE 1 -static ssize_t -show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = w83795_update_device(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index >> 3; - int bit = sensor_attr->index & 0x07; - u8 val; - - if (nr == ALARM_STATUS) - val = (data->alarms[index] >> bit) & 1; - else /* BEEP_ENABLE */ - val = (data->beeps[index] >> bit) & 1; - - return sprintf(buf, "%u\n", val); -} - -static ssize_t -store_beep(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index >> 3; - int shift = sensor_attr->index & 0x07; - u8 beep_bit = 1 << shift; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - if (val != 0 && val != 1) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->beeps[index] = w83795_read(client, W83795_REG_BEEP(index)); - data->beeps[index] &= ~beep_bit; - data->beeps[index] |= val << shift; - w83795_write(client, W83795_REG_BEEP(index), data->beeps[index]); - mutex_unlock(&data->update_lock); - - return count; -} - -/* Write 0 to clear chassis alarm */ -static ssize_t -store_chassis_clear(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0 || val != 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - val = w83795_read(client, W83795_REG_CLR_CHASSIS); - val |= 0x80; - w83795_write(client, W83795_REG_CLR_CHASSIS, val); - - /* Clear status and force cache refresh */ - w83795_read(client, W83795_REG_ALARM(5)); - data->valid = 0; - mutex_unlock(&data->update_lock); - return count; -} - -#define FAN_INPUT 0 -#define FAN_MIN 1 -static ssize_t -show_fan(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83795_data *data = w83795_update_device(dev); - u16 val; - - if (nr == FAN_INPUT) - val = data->fan[index] & 0x0fff; - else - val = data->fan_min[index] & 0x0fff; - - return sprintf(buf, "%lu\n", fan_from_reg(val)); -} - -static ssize_t -store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val)) - return -EINVAL; - val = fan_to_reg(val); - - mutex_lock(&data->update_lock); - data->fan_min[index] = val; - w83795_write(client, W83795_REG_FAN_MIN_HL(index), (val >> 4) & 0xff); - val &= 0x0f; - if (index & 1) { - val <<= 4; - val |= w83795_read(client, W83795_REG_FAN_MIN_LSB(index)) - & 0x0f; - } else { - val |= w83795_read(client, W83795_REG_FAN_MIN_LSB(index)) - & 0xf0; - } - w83795_write(client, W83795_REG_FAN_MIN_LSB(index), val & 0xff); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_pwm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data; - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned int val; - - data = nr == PWM_OUTPUT ? w83795_update_device(dev) - : w83795_update_pwm_config(dev); - - switch (nr) { - case PWM_STOP_TIME: - val = time_from_reg(data->pwm[index][nr]); - break; - case PWM_FREQ: - val = pwm_freq_from_reg(data->pwm[index][nr], data->clkin); - break; - default: - val = data->pwm[index][nr]; - break; - } - - return sprintf(buf, "%u\n", val); -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - switch (nr) { - case PWM_STOP_TIME: - val = time_to_reg(val); - break; - case PWM_FREQ: - val = pwm_freq_to_reg(val, data->clkin); - break; - default: - val = SENSORS_LIMIT(val, 0, 0xff); - break; - } - w83795_write(client, W83795_REG_PWM(index, nr), val); - data->pwm[index][nr] = val; - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - struct w83795_data *data = w83795_update_pwm_config(dev); - int index = sensor_attr->index; - u8 tmp; - - /* Speed cruise mode */ - if (data->pwm_fcms[0] & (1 << index)) { - tmp = 2; - goto out; - } - /* Thermal cruise or SmartFan IV mode */ - for (tmp = 0; tmp < 6; tmp++) { - if (data->pwm_tfmr[tmp] & (1 << index)) { - tmp = 3; - goto out; - } - } - /* Manual mode */ - tmp = 1; - -out: - return sprintf(buf, "%u\n", tmp); -} - -static ssize_t -store_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - unsigned long val; - int i; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - if (val < 1 || val > 2) - return -EINVAL; - -#ifndef CONFIG_SENSORS_W83795_FANCTRL - if (val > 1) { - dev_warn(dev, "Automatic fan speed control support disabled\n"); - dev_warn(dev, "Build with CONFIG_SENSORS_W83795_FANCTRL=y if you want it\n"); - return -EOPNOTSUPP; - } -#endif - - mutex_lock(&data->update_lock); - switch (val) { - case 1: - /* Clear speed cruise mode bits */ - data->pwm_fcms[0] &= ~(1 << index); - w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]); - /* Clear thermal cruise mode bits */ - for (i = 0; i < 6; i++) { - data->pwm_tfmr[i] &= ~(1 << index); - w83795_write(client, W83795_REG_TFMR(i), - data->pwm_tfmr[i]); - } - break; - case 2: - data->pwm_fcms[0] |= (1 << index); - w83795_write(client, W83795_REG_FCMS1, data->pwm_fcms[0]); - break; - } - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -show_pwm_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = w83795_update_pwm_config(dev); - int index = to_sensor_dev_attr_2(attr)->index; - unsigned int mode; - - if (data->pwm_fomc & (1 << index)) - mode = 0; /* DC */ - else - mode = 1; /* PWM */ - - return sprintf(buf, "%u\n", mode); -} - -/* - * Check whether a given temperature source can ever be useful. - * Returns the number of selectable temperature channels which are - * enabled. - */ -static int w83795_tss_useful(const struct w83795_data *data, int tsrc) -{ - int useful = 0, i; - - for (i = 0; i < 4; i++) { - if (tss_map[i][tsrc] == TSS_MAP_RESERVED) - continue; - if (tss_map[i][tsrc] < 6) /* Analog */ - useful += (data->has_temp >> tss_map[i][tsrc]) & 1; - else /* Digital */ - useful += (data->has_dts >> (tss_map[i][tsrc] - 6)) & 1; - } - - return useful; -} - -static ssize_t -show_temp_src(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - struct w83795_data *data = w83795_update_pwm_config(dev); - int index = sensor_attr->index; - u8 tmp = data->temp_src[index / 2]; - - if (index & 1) - tmp >>= 4; /* Pick high nibble */ - else - tmp &= 0x0f; /* Pick low nibble */ - - /* Look-up the actual temperature channel number */ - if (tmp >= 4 || tss_map[tmp][index] == TSS_MAP_RESERVED) - return -EINVAL; /* Shouldn't happen */ - - return sprintf(buf, "%u\n", (unsigned int)tss_map[tmp][index] + 1); -} - -static ssize_t -store_temp_src(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - int tmp; - unsigned long channel; - u8 val = index / 2; - - if (kstrtoul(buf, 10, &channel) < 0 || - channel < 1 || channel > 14) - return -EINVAL; - - /* Check if request can be fulfilled */ - for (tmp = 0; tmp < 4; tmp++) { - if (tss_map[tmp][index] == channel - 1) - break; - } - if (tmp == 4) /* No match */ - return -EINVAL; - - mutex_lock(&data->update_lock); - if (index & 1) { - tmp <<= 4; - data->temp_src[val] &= 0x0f; - } else { - data->temp_src[val] &= 0xf0; - } - data->temp_src[val] |= tmp; - w83795_write(client, W83795_REG_TSS(val), data->temp_src[val]); - mutex_unlock(&data->update_lock); - - return count; -} - -#define TEMP_PWM_ENABLE 0 -#define TEMP_PWM_FAN_MAP 1 -static ssize_t -show_temp_pwm_enable(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - u8 tmp = 0xff; - - switch (nr) { - case TEMP_PWM_ENABLE: - tmp = (data->pwm_fcms[1] >> index) & 1; - if (tmp) - tmp = 4; - else - tmp = 3; - break; - case TEMP_PWM_FAN_MAP: - tmp = data->pwm_tfmr[index]; - break; - } - - return sprintf(buf, "%u\n", tmp); -} - -static ssize_t -store_temp_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long tmp; - - if (kstrtoul(buf, 10, &tmp) < 0) - return -EINVAL; - - switch (nr) { - case TEMP_PWM_ENABLE: - if (tmp != 3 && tmp != 4) - return -EINVAL; - tmp -= 3; - mutex_lock(&data->update_lock); - data->pwm_fcms[1] &= ~(1 << index); - data->pwm_fcms[1] |= tmp << index; - w83795_write(client, W83795_REG_FCMS2, data->pwm_fcms[1]); - mutex_unlock(&data->update_lock); - break; - case TEMP_PWM_FAN_MAP: - mutex_lock(&data->update_lock); - tmp = SENSORS_LIMIT(tmp, 0, 0xff); - w83795_write(client, W83795_REG_TFMR(index), tmp); - data->pwm_tfmr[index] = tmp; - mutex_unlock(&data->update_lock); - break; - } - return count; -} - -#define FANIN_TARGET 0 -#define FANIN_TOL 1 -static ssize_t -show_fanin(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - u16 tmp = 0; - - switch (nr) { - case FANIN_TARGET: - tmp = fan_from_reg(data->target_speed[index]); - break; - case FANIN_TOL: - tmp = data->tol_speed; - break; - } - - return sprintf(buf, "%u\n", tmp); -} - -static ssize_t -store_fanin(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - switch (nr) { - case FANIN_TARGET: - val = fan_to_reg(SENSORS_LIMIT(val, 0, 0xfff)); - w83795_write(client, W83795_REG_FTSH(index), val >> 4); - w83795_write(client, W83795_REG_FTSL(index), (val << 4) & 0xf0); - data->target_speed[index] = val; - break; - case FANIN_TOL: - val = SENSORS_LIMIT(val, 0, 0x3f); - w83795_write(client, W83795_REG_TFTS, val); - data->tol_speed = val; - break; - } - mutex_unlock(&data->update_lock); - - return count; -} - - -static ssize_t -show_temp_pwm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - long tmp = temp_from_reg(data->pwm_temp[index][nr]); - - return sprintf(buf, "%ld\n", tmp); -} - -static ssize_t -store_temp_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - u8 tmp; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - val /= 1000; - - mutex_lock(&data->update_lock); - switch (nr) { - case TEMP_PWM_TTTI: - val = SENSORS_LIMIT(val, 0, 0x7f); - w83795_write(client, W83795_REG_TTTI(index), val); - break; - case TEMP_PWM_CTFS: - val = SENSORS_LIMIT(val, 0, 0x7f); - w83795_write(client, W83795_REG_CTFS(index), val); - break; - case TEMP_PWM_HCT: - val = SENSORS_LIMIT(val, 0, 0x0f); - tmp = w83795_read(client, W83795_REG_HT(index)); - tmp &= 0x0f; - tmp |= (val << 4) & 0xf0; - w83795_write(client, W83795_REG_HT(index), tmp); - break; - case TEMP_PWM_HOT: - val = SENSORS_LIMIT(val, 0, 0x0f); - tmp = w83795_read(client, W83795_REG_HT(index)); - tmp &= 0xf0; - tmp |= val & 0x0f; - w83795_write(client, W83795_REG_HT(index), tmp); - break; - } - data->pwm_temp[index][nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_sf4_pwm(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - - return sprintf(buf, "%u\n", data->sf4_reg[index][SF4_PWM][nr]); -} - -static ssize_t -store_sf4_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - w83795_write(client, W83795_REG_SF4_PWM(index, nr), val); - data->sf4_reg[index][SF4_PWM][nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_sf4_temp(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = w83795_update_pwm_config(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - - return sprintf(buf, "%u\n", - (data->sf4_reg[index][SF4_TEMP][nr]) * 1000); -} - -static ssize_t -store_sf4_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - val /= 1000; - - mutex_lock(&data->update_lock); - w83795_write(client, W83795_REG_SF4_TEMP(index, nr), val); - data->sf4_reg[index][SF4_TEMP][nr] = val; - mutex_unlock(&data->update_lock); - - return count; -} - - -static ssize_t -show_temp(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83795_data *data = w83795_update_device(dev); - long temp = temp_from_reg(data->temp[index][nr]); - - if (nr == TEMP_READ) - temp += (data->temp_read_vrlsb[index] >> 6) * 250; - return sprintf(buf, "%ld\n", temp); -} - -static ssize_t -store_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - long tmp; - - if (kstrtol(buf, 10, &tmp) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->temp[index][nr] = temp_to_reg(tmp, -128, 127); - w83795_write(client, W83795_REG_TEMP[index][nr], data->temp[index][nr]); - mutex_unlock(&data->update_lock); - return count; -} - - -static ssize_t -show_dts_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = dev_get_drvdata(dev); - int tmp; - - if (data->enable_dts & 2) - tmp = 5; - else - tmp = 6; - - return sprintf(buf, "%d\n", tmp); -} - -static ssize_t -show_dts(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - struct w83795_data *data = w83795_update_device(dev); - long temp = temp_from_reg(data->dts[index]); - - temp += (data->dts_read_vrlsb[index] >> 6) * 250; - return sprintf(buf, "%ld\n", temp); -} - -static ssize_t -show_dts_ext(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - struct w83795_data *data = dev_get_drvdata(dev); - long temp = temp_from_reg(data->dts_ext[nr]); - - return sprintf(buf, "%ld\n", temp); -} - -static ssize_t -store_dts_ext(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - long tmp; - - if (kstrtol(buf, 10, &tmp) < 0) - return -EINVAL; - - mutex_lock(&data->update_lock); - data->dts_ext[nr] = temp_to_reg(tmp, -128, 127); - w83795_write(client, W83795_REG_DTS_EXT(nr), data->dts_ext[nr]); - mutex_unlock(&data->update_lock); - return count; -} - - -static ssize_t -show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83795_data *data = dev_get_drvdata(dev); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - int tmp; - - if (data->temp_mode & (1 << index)) - tmp = 3; /* Thermal diode */ - else - tmp = 4; /* Thermistor */ - - return sprintf(buf, "%d\n", tmp); -} - -/* Only for temp1-4 (temp5-6 can only be thermistor) */ -static ssize_t -store_temp_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int index = sensor_attr->index; - int reg_shift; - unsigned long val; - u8 tmp; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - if ((val != 4) && (val != 3)) - return -EINVAL; - - mutex_lock(&data->update_lock); - if (val == 3) { - /* Thermal diode */ - val = 0x01; - data->temp_mode |= 1 << index; - } else if (val == 4) { - /* Thermistor */ - val = 0x03; - data->temp_mode &= ~(1 << index); - } - - reg_shift = 2 * index; - tmp = w83795_read(client, W83795_REG_TEMP_CTRL2); - tmp &= ~(0x03 << reg_shift); - tmp |= val << reg_shift; - w83795_write(client, W83795_REG_TEMP_CTRL2, tmp); - - mutex_unlock(&data->update_lock); - return count; -} - - -/* show/store VIN */ -static ssize_t -show_in(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83795_data *data = w83795_update_device(dev); - u16 val = data->in[index][nr]; - u8 lsb_idx; - - switch (nr) { - case IN_READ: - /* calculate this value again by sensors as sensors3.conf */ - if ((index >= 17) && - !((data->has_gain >> (index - 17)) & 1)) - val *= 8; - break; - case IN_MAX: - case IN_LOW: - lsb_idx = IN_LSB_SHIFT_IDX[index][IN_LSB_IDX]; - val <<= 2; - val |= (data->in_lsb[lsb_idx][nr] >> - IN_LSB_SHIFT_IDX[index][IN_LSB_SHIFT]) & 0x03; - if ((index >= 17) && - !((data->has_gain >> (index - 17)) & 1)) - val *= 8; - break; - } - val = in_from_reg(index, val); - - return sprintf(buf, "%d\n", val); -} - -static ssize_t -store_in(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - unsigned long val; - u8 tmp; - u8 lsb_idx; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - val = in_to_reg(index, val); - - if ((index >= 17) && - !((data->has_gain >> (index - 17)) & 1)) - val /= 8; - val = SENSORS_LIMIT(val, 0, 0x3FF); - mutex_lock(&data->update_lock); - - lsb_idx = IN_LSB_SHIFT_IDX[index][IN_LSB_IDX]; - tmp = w83795_read(client, IN_LSB_REG(lsb_idx, nr)); - tmp &= ~(0x03 << IN_LSB_SHIFT_IDX[index][IN_LSB_SHIFT]); - tmp |= (val & 0x03) << IN_LSB_SHIFT_IDX[index][IN_LSB_SHIFT]; - w83795_write(client, IN_LSB_REG(lsb_idx, nr), tmp); - data->in_lsb[lsb_idx][nr] = tmp; - - tmp = (val >> 2) & 0xff; - w83795_write(client, W83795_REG_IN[index][nr], tmp); - data->in[index][nr] = tmp; - - mutex_unlock(&data->update_lock); - return count; -} - - -#ifdef CONFIG_SENSORS_W83795_FANCTRL -static ssize_t -show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - struct w83795_data *data = w83795_update_pwm_config(dev); - u16 val = data->setup_pwm[nr]; - - switch (nr) { - case SETUP_PWM_UPTIME: - case SETUP_PWM_DOWNTIME: - val = time_from_reg(val); - break; - } - - return sprintf(buf, "%d\n", val); -} - -static ssize_t -store_sf_setup(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - struct i2c_client *client = to_i2c_client(dev); - struct w83795_data *data = i2c_get_clientdata(client); - unsigned long val; - - if (kstrtoul(buf, 10, &val) < 0) - return -EINVAL; - - switch (nr) { - case SETUP_PWM_DEFAULT: - val = SENSORS_LIMIT(val, 0, 0xff); - break; - case SETUP_PWM_UPTIME: - case SETUP_PWM_DOWNTIME: - val = time_to_reg(val); - if (val == 0) - return -EINVAL; - break; - } - - mutex_lock(&data->update_lock); - data->setup_pwm[nr] = val; - w83795_write(client, W83795_REG_SETUP_PWM(nr), val); - mutex_unlock(&data->update_lock); - return count; -} -#endif - - -#define NOT_USED -1 - -/* - * Don't change the attribute order, _max, _min and _beep are accessed by index - * somewhere else in the code - */ -#define SENSOR_ATTR_IN(index) { \ - SENSOR_ATTR_2(in##index##_input, S_IRUGO, show_in, NULL, \ - IN_READ, index), \ - SENSOR_ATTR_2(in##index##_max, S_IRUGO | S_IWUSR, show_in, \ - store_in, IN_MAX, index), \ - SENSOR_ATTR_2(in##index##_min, S_IRUGO | S_IWUSR, show_in, \ - store_in, IN_LOW, index), \ - SENSOR_ATTR_2(in##index##_alarm, S_IRUGO, show_alarm_beep, \ - NULL, ALARM_STATUS, index + ((index > 14) ? 1 : 0)), \ - SENSOR_ATTR_2(in##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, \ - index + ((index > 14) ? 1 : 0)) } - -/* - * Don't change the attribute order, _beep is accessed by index - * somewhere else in the code - */ -#define SENSOR_ATTR_FAN(index) { \ - SENSOR_ATTR_2(fan##index##_input, S_IRUGO, show_fan, \ - NULL, FAN_INPUT, index - 1), \ - SENSOR_ATTR_2(fan##index##_min, S_IWUSR | S_IRUGO, \ - show_fan, store_fan_min, FAN_MIN, index - 1), \ - SENSOR_ATTR_2(fan##index##_alarm, S_IRUGO, show_alarm_beep, \ - NULL, ALARM_STATUS, index + 31), \ - SENSOR_ATTR_2(fan##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, index + 31) } - -#define SENSOR_ATTR_PWM(index) { \ - SENSOR_ATTR_2(pwm##index, S_IWUSR | S_IRUGO, show_pwm, \ - store_pwm, PWM_OUTPUT, index - 1), \ - SENSOR_ATTR_2(pwm##index##_enable, S_IWUSR | S_IRUGO, \ - show_pwm_enable, store_pwm_enable, NOT_USED, index - 1), \ - SENSOR_ATTR_2(pwm##index##_mode, S_IRUGO, \ - show_pwm_mode, NULL, NOT_USED, index - 1), \ - SENSOR_ATTR_2(pwm##index##_freq, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_FREQ, index - 1), \ - SENSOR_ATTR_2(pwm##index##_nonstop, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_NONSTOP, index - 1), \ - SENSOR_ATTR_2(pwm##index##_start, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_START, index - 1), \ - SENSOR_ATTR_2(pwm##index##_stop_time, S_IWUSR | S_IRUGO, \ - show_pwm, store_pwm, PWM_STOP_TIME, index - 1), \ - SENSOR_ATTR_2(fan##index##_target, S_IWUSR | S_IRUGO, \ - show_fanin, store_fanin, FANIN_TARGET, index - 1) } - -/* - * Don't change the attribute order, _beep is accessed by index - * somewhere else in the code - */ -#define SENSOR_ATTR_DTS(index) { \ - SENSOR_ATTR_2(temp##index##_type, S_IRUGO , \ - show_dts_mode, NULL, NOT_USED, index - 7), \ - SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_dts, \ - NULL, NOT_USED, index - 7), \ - SENSOR_ATTR_2(temp##index##_crit, S_IRUGO | S_IWUSR, show_dts_ext, \ - store_dts_ext, DTS_CRIT, NOT_USED), \ - SENSOR_ATTR_2(temp##index##_crit_hyst, S_IRUGO | S_IWUSR, \ - show_dts_ext, store_dts_ext, DTS_CRIT_HYST, NOT_USED), \ - SENSOR_ATTR_2(temp##index##_max, S_IRUGO | S_IWUSR, show_dts_ext, \ - store_dts_ext, DTS_WARN, NOT_USED), \ - SENSOR_ATTR_2(temp##index##_max_hyst, S_IRUGO | S_IWUSR, \ - show_dts_ext, store_dts_ext, DTS_WARN_HYST, NOT_USED), \ - SENSOR_ATTR_2(temp##index##_alarm, S_IRUGO, \ - show_alarm_beep, NULL, ALARM_STATUS, index + 17), \ - SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) } - -/* - * Don't change the attribute order, _beep is accessed by index - * somewhere else in the code - */ -#define SENSOR_ATTR_TEMP(index) { \ - SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \ - show_temp_mode, store_temp_mode, NOT_USED, index - 1), \ - SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp, \ - NULL, TEMP_READ, index - 1), \ - SENSOR_ATTR_2(temp##index##_crit, S_IRUGO | S_IWUSR, show_temp, \ - store_temp, TEMP_CRIT, index - 1), \ - SENSOR_ATTR_2(temp##index##_crit_hyst, S_IRUGO | S_IWUSR, \ - show_temp, store_temp, TEMP_CRIT_HYST, index - 1), \ - SENSOR_ATTR_2(temp##index##_max, S_IRUGO | S_IWUSR, show_temp, \ - store_temp, TEMP_WARN, index - 1), \ - SENSOR_ATTR_2(temp##index##_max_hyst, S_IRUGO | S_IWUSR, \ - show_temp, store_temp, TEMP_WARN_HYST, index - 1), \ - SENSOR_ATTR_2(temp##index##_alarm, S_IRUGO, \ - show_alarm_beep, NULL, ALARM_STATUS, \ - index + (index > 4 ? 11 : 17)), \ - SENSOR_ATTR_2(temp##index##_beep, S_IWUSR | S_IRUGO, \ - show_alarm_beep, store_beep, BEEP_ENABLE, \ - index + (index > 4 ? 11 : 17)), \ - SENSOR_ATTR_2(temp##index##_pwm_enable, S_IWUSR | S_IRUGO, \ - show_temp_pwm_enable, store_temp_pwm_enable, \ - TEMP_PWM_ENABLE, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_channels_pwm, S_IWUSR | S_IRUGO, \ - show_temp_pwm_enable, store_temp_pwm_enable, \ - TEMP_PWM_FAN_MAP, index - 1), \ - SENSOR_ATTR_2(thermal_cruise##index, S_IWUSR | S_IRUGO, \ - show_temp_pwm, store_temp_pwm, TEMP_PWM_TTTI, index - 1), \ - SENSOR_ATTR_2(temp##index##_warn, S_IWUSR | S_IRUGO, \ - show_temp_pwm, store_temp_pwm, TEMP_PWM_CTFS, index - 1), \ - SENSOR_ATTR_2(temp##index##_warn_hyst, S_IWUSR | S_IRUGO, \ - show_temp_pwm, store_temp_pwm, TEMP_PWM_HCT, index - 1), \ - SENSOR_ATTR_2(temp##index##_operation_hyst, S_IWUSR | S_IRUGO, \ - show_temp_pwm, store_temp_pwm, TEMP_PWM_HOT, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point1_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 0, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point2_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 1, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point3_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 2, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point4_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 3, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point5_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 4, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point6_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 5, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point7_pwm, S_IRUGO | S_IWUSR, \ - show_sf4_pwm, store_sf4_pwm, 6, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point1_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 0, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point2_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 1, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point3_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 2, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point4_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 3, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point5_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 4, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point6_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 5, index - 1), \ - SENSOR_ATTR_2(temp##index##_auto_point7_temp, S_IRUGO | S_IWUSR,\ - show_sf4_temp, store_sf4_temp, 6, index - 1) } - - -static struct sensor_device_attribute_2 w83795_in[][5] = { - SENSOR_ATTR_IN(0), - SENSOR_ATTR_IN(1), - SENSOR_ATTR_IN(2), - SENSOR_ATTR_IN(3), - SENSOR_ATTR_IN(4), - SENSOR_ATTR_IN(5), - SENSOR_ATTR_IN(6), - SENSOR_ATTR_IN(7), - SENSOR_ATTR_IN(8), - SENSOR_ATTR_IN(9), - SENSOR_ATTR_IN(10), - SENSOR_ATTR_IN(11), - SENSOR_ATTR_IN(12), - SENSOR_ATTR_IN(13), - SENSOR_ATTR_IN(14), - SENSOR_ATTR_IN(15), - SENSOR_ATTR_IN(16), - SENSOR_ATTR_IN(17), - SENSOR_ATTR_IN(18), - SENSOR_ATTR_IN(19), - SENSOR_ATTR_IN(20), -}; - -static const struct sensor_device_attribute_2 w83795_fan[][4] = { - SENSOR_ATTR_FAN(1), - SENSOR_ATTR_FAN(2), - SENSOR_ATTR_FAN(3), - SENSOR_ATTR_FAN(4), - SENSOR_ATTR_FAN(5), - SENSOR_ATTR_FAN(6), - SENSOR_ATTR_FAN(7), - SENSOR_ATTR_FAN(8), - SENSOR_ATTR_FAN(9), - SENSOR_ATTR_FAN(10), - SENSOR_ATTR_FAN(11), - SENSOR_ATTR_FAN(12), - SENSOR_ATTR_FAN(13), - SENSOR_ATTR_FAN(14), -}; - -static const struct sensor_device_attribute_2 w83795_temp[][28] = { - SENSOR_ATTR_TEMP(1), - SENSOR_ATTR_TEMP(2), - SENSOR_ATTR_TEMP(3), - SENSOR_ATTR_TEMP(4), - SENSOR_ATTR_TEMP(5), - SENSOR_ATTR_TEMP(6), -}; - -static const struct sensor_device_attribute_2 w83795_dts[][8] = { - SENSOR_ATTR_DTS(7), - SENSOR_ATTR_DTS(8), - SENSOR_ATTR_DTS(9), - SENSOR_ATTR_DTS(10), - SENSOR_ATTR_DTS(11), - SENSOR_ATTR_DTS(12), - SENSOR_ATTR_DTS(13), - SENSOR_ATTR_DTS(14), -}; - -static const struct sensor_device_attribute_2 w83795_pwm[][8] = { - SENSOR_ATTR_PWM(1), - SENSOR_ATTR_PWM(2), - SENSOR_ATTR_PWM(3), - SENSOR_ATTR_PWM(4), - SENSOR_ATTR_PWM(5), - SENSOR_ATTR_PWM(6), - SENSOR_ATTR_PWM(7), - SENSOR_ATTR_PWM(8), -}; - -static const struct sensor_device_attribute_2 w83795_tss[6] = { - SENSOR_ATTR_2(temp1_source_sel, S_IWUSR | S_IRUGO, - show_temp_src, store_temp_src, NOT_USED, 0), - SENSOR_ATTR_2(temp2_source_sel, S_IWUSR | S_IRUGO, - show_temp_src, store_temp_src, NOT_USED, 1), - SENSOR_ATTR_2(temp3_source_sel, S_IWUSR | S_IRUGO, - show_temp_src, store_temp_src, NOT_USED, 2), - SENSOR_ATTR_2(temp4_source_sel, S_IWUSR | S_IRUGO, - show_temp_src, store_temp_src, NOT_USED, 3), - SENSOR_ATTR_2(temp5_source_sel, S_IWUSR | S_IRUGO, - show_temp_src, store_temp_src, NOT_USED, 4), - SENSOR_ATTR_2(temp6_source_sel, S_IWUSR | S_IRUGO, - show_temp_src, store_temp_src, NOT_USED, 5), -}; - -static const struct sensor_device_attribute_2 sda_single_files[] = { - SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, - store_chassis_clear, ALARM_STATUS, 46), -#ifdef CONFIG_SENSORS_W83795_FANCTRL - SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin, - store_fanin, FANIN_TOL, NOT_USED), - SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_PWM_DEFAULT, NOT_USED), - SENSOR_ATTR_2(pwm_uptime, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_PWM_UPTIME, NOT_USED), - SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup, - store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED), -#endif -}; - -static const struct sensor_device_attribute_2 sda_beep_files[] = { - SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep, - store_beep, BEEP_ENABLE, 46), - SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep, - store_beep, BEEP_ENABLE, 47), -}; - -/* - * Driver interface - */ - -static void w83795_init_client(struct i2c_client *client) -{ - struct w83795_data *data = i2c_get_clientdata(client); - static const u16 clkin[4] = { /* in kHz */ - 14318, 24000, 33333, 48000 - }; - u8 config; - - if (reset) - w83795_write(client, W83795_REG_CONFIG, 0x80); - - /* Start monitoring if needed */ - config = w83795_read(client, W83795_REG_CONFIG); - if (!(config & W83795_REG_CONFIG_START)) { - dev_info(&client->dev, "Enabling monitoring operations\n"); - w83795_write(client, W83795_REG_CONFIG, - config | W83795_REG_CONFIG_START); - } - - data->clkin = clkin[(config >> 3) & 0x3]; - dev_dbg(&client->dev, "clkin = %u kHz\n", data->clkin); -} - -static int w83795_get_device_id(struct i2c_client *client) -{ - int device_id; - - device_id = i2c_smbus_read_byte_data(client, W83795_REG_DEVICEID); - - /* - * Special case for rev. A chips; can't be checked first because later - * revisions emulate this for compatibility - */ - if (device_id < 0 || (device_id & 0xf0) != 0x50) { - int alt_id; - - alt_id = i2c_smbus_read_byte_data(client, - W83795_REG_DEVICEID_A); - if (alt_id == 0x50) - device_id = alt_id; - } - - return device_id; -} - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83795_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - int bank, vendor_id, device_id, expected, i2c_addr, config; - struct i2c_adapter *adapter = client->adapter; - unsigned short address = client->addr; - const char *chip_name; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL); - if (bank < 0 || (bank & 0x7c)) { - dev_dbg(&adapter->dev, - "w83795: Detection failed at addr 0x%02hx, check %s\n", - address, "bank"); - return -ENODEV; - } - - /* Check Nuvoton vendor ID */ - vendor_id = i2c_smbus_read_byte_data(client, W83795_REG_VENDORID); - expected = bank & 0x80 ? 0x5c : 0xa3; - if (vendor_id != expected) { - dev_dbg(&adapter->dev, - "w83795: Detection failed at addr 0x%02hx, check %s\n", - address, "vendor id"); - return -ENODEV; - } - - /* Check device ID */ - device_id = w83795_get_device_id(client) | - (i2c_smbus_read_byte_data(client, W83795_REG_CHIPID) << 8); - if ((device_id >> 4) != 0x795) { - dev_dbg(&adapter->dev, - "w83795: Detection failed at addr 0x%02hx, check %s\n", - address, "device id\n"); - return -ENODEV; - } - - /* - * If Nuvoton chip, address of chip and W83795_REG_I2C_ADDR - * should match - */ - if ((bank & 0x07) == 0) { - i2c_addr = i2c_smbus_read_byte_data(client, - W83795_REG_I2C_ADDR); - if ((i2c_addr & 0x7f) != address) { - dev_dbg(&adapter->dev, - "w83795: Detection failed at addr 0x%02hx, " - "check %s\n", address, "i2c addr"); - return -ENODEV; - } - } - - /* - * Check 795 chip type: 795G or 795ADG - * Usually we don't write to chips during detection, but here we don't - * quite have the choice; hopefully it's OK, we are about to return - * success anyway - */ - if ((bank & 0x07) != 0) - i2c_smbus_write_byte_data(client, W83795_REG_BANKSEL, - bank & ~0x07); - config = i2c_smbus_read_byte_data(client, W83795_REG_CONFIG); - if (config & W83795_REG_CONFIG_CONFIG48) - chip_name = "w83795adg"; - else - chip_name = "w83795g"; - - strlcpy(info->type, chip_name, I2C_NAME_SIZE); - dev_info(&adapter->dev, "Found %s rev. %c at 0x%02hx\n", chip_name, - 'A' + (device_id & 0xf), address); - - return 0; -} - -#ifdef CONFIG_SENSORS_W83795_FANCTRL -#define NUM_PWM_ATTRIBUTES ARRAY_SIZE(w83795_pwm[0]) -#define NUM_TEMP_ATTRIBUTES ARRAY_SIZE(w83795_temp[0]) -#else -#define NUM_PWM_ATTRIBUTES 4 -#define NUM_TEMP_ATTRIBUTES 8 -#endif - -static int w83795_handle_files(struct device *dev, int (*fn)(struct device *, - const struct device_attribute *)) -{ - struct w83795_data *data = dev_get_drvdata(dev); - int err, i, j; - - for (i = 0; i < ARRAY_SIZE(w83795_in); i++) { - if (!(data->has_in & (1 << i))) - continue; - for (j = 0; j < ARRAY_SIZE(w83795_in[0]); j++) { - if (j == 4 && !data->enable_beep) - continue; - err = fn(dev, &w83795_in[i][j].dev_attr); - if (err) - return err; - } - } - - for (i = 0; i < ARRAY_SIZE(w83795_fan); i++) { - if (!(data->has_fan & (1 << i))) - continue; - for (j = 0; j < ARRAY_SIZE(w83795_fan[0]); j++) { - if (j == 3 && !data->enable_beep) - continue; - err = fn(dev, &w83795_fan[i][j].dev_attr); - if (err) - return err; - } - } - - for (i = 0; i < ARRAY_SIZE(w83795_tss); i++) { - j = w83795_tss_useful(data, i); - if (!j) - continue; - err = fn(dev, &w83795_tss[i].dev_attr); - if (err) - return err; - } - - for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) { - err = fn(dev, &sda_single_files[i].dev_attr); - if (err) - return err; - } - - if (data->enable_beep) { - for (i = 0; i < ARRAY_SIZE(sda_beep_files); i++) { - err = fn(dev, &sda_beep_files[i].dev_attr); - if (err) - return err; - } - } - - for (i = 0; i < data->has_pwm; i++) { - for (j = 0; j < NUM_PWM_ATTRIBUTES; j++) { - err = fn(dev, &w83795_pwm[i][j].dev_attr); - if (err) - return err; - } - } - - for (i = 0; i < ARRAY_SIZE(w83795_temp); i++) { - if (!(data->has_temp & (1 << i))) - continue; - for (j = 0; j < NUM_TEMP_ATTRIBUTES; j++) { - if (j == 7 && !data->enable_beep) - continue; - err = fn(dev, &w83795_temp[i][j].dev_attr); - if (err) - return err; - } - } - - if (data->enable_dts) { - for (i = 0; i < ARRAY_SIZE(w83795_dts); i++) { - if (!(data->has_dts & (1 << i))) - continue; - for (j = 0; j < ARRAY_SIZE(w83795_dts[0]); j++) { - if (j == 7 && !data->enable_beep) - continue; - err = fn(dev, &w83795_dts[i][j].dev_attr); - if (err) - return err; - } - } - } - - return 0; -} - -/* We need a wrapper that fits in w83795_handle_files */ -static int device_remove_file_wrapper(struct device *dev, - const struct device_attribute *attr) -{ - device_remove_file(dev, attr); - return 0; -} - -static void w83795_check_dynamic_in_limits(struct i2c_client *client) -{ - struct w83795_data *data = i2c_get_clientdata(client); - u8 vid_ctl; - int i, err_max, err_min; - - vid_ctl = w83795_read(client, W83795_REG_VID_CTRL); - - /* Return immediately if VRM isn't configured */ - if ((vid_ctl & 0x07) == 0x00 || (vid_ctl & 0x07) == 0x07) - return; - - data->has_dyn_in = (vid_ctl >> 3) & 0x07; - for (i = 0; i < 2; i++) { - if (!(data->has_dyn_in & (1 << i))) - continue; - - /* Voltage limits in dynamic mode, switch to read-only */ - err_max = sysfs_chmod_file(&client->dev.kobj, - &w83795_in[i][2].dev_attr.attr, - S_IRUGO); - err_min = sysfs_chmod_file(&client->dev.kobj, - &w83795_in[i][3].dev_attr.attr, - S_IRUGO); - if (err_max || err_min) - dev_warn(&client->dev, "Failed to set in%d limits " - "read-only (%d, %d)\n", i, err_max, err_min); - else - dev_info(&client->dev, "in%d limits set dynamically " - "from VID\n", i); - } -} - -/* Check pins that can be used for either temperature or voltage monitoring */ -static void w83795_apply_temp_config(struct w83795_data *data, u8 config, - int temp_chan, int in_chan) -{ - /* config is a 2-bit value */ - switch (config) { - case 0x2: /* Voltage monitoring */ - data->has_in |= 1 << in_chan; - break; - case 0x1: /* Thermal diode */ - if (temp_chan >= 4) - break; - data->temp_mode |= 1 << temp_chan; - /* fall through */ - case 0x3: /* Thermistor */ - data->has_temp |= 1 << temp_chan; - break; - } -} - -static int w83795_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - int i; - u8 tmp; - struct device *dev = &client->dev; - struct w83795_data *data; - int err; - - data = kzalloc(sizeof(struct w83795_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - data->chip_type = id->driver_data; - data->bank = i2c_smbus_read_byte_data(client, W83795_REG_BANKSEL); - mutex_init(&data->update_lock); - - /* Initialize the chip */ - w83795_init_client(client); - - /* Check which voltages and fans are present */ - data->has_in = w83795_read(client, W83795_REG_VOLT_CTRL1) - | (w83795_read(client, W83795_REG_VOLT_CTRL2) << 8); - data->has_fan = w83795_read(client, W83795_REG_FANIN_CTRL1) - | (w83795_read(client, W83795_REG_FANIN_CTRL2) << 8); - - /* Check which analog temperatures and extra voltages are present */ - tmp = w83795_read(client, W83795_REG_TEMP_CTRL1); - if (tmp & 0x20) - data->enable_dts = 1; - w83795_apply_temp_config(data, (tmp >> 2) & 0x3, 5, 16); - w83795_apply_temp_config(data, tmp & 0x3, 4, 15); - tmp = w83795_read(client, W83795_REG_TEMP_CTRL2); - w83795_apply_temp_config(data, tmp >> 6, 3, 20); - w83795_apply_temp_config(data, (tmp >> 4) & 0x3, 2, 19); - w83795_apply_temp_config(data, (tmp >> 2) & 0x3, 1, 18); - w83795_apply_temp_config(data, tmp & 0x3, 0, 17); - - /* Check DTS enable status */ - if (data->enable_dts) { - if (1 & w83795_read(client, W83795_REG_DTSC)) - data->enable_dts |= 2; - data->has_dts = w83795_read(client, W83795_REG_DTSE); - } - - /* Report PECI Tbase values */ - if (data->enable_dts == 1) { - for (i = 0; i < 8; i++) { - if (!(data->has_dts & (1 << i))) - continue; - tmp = w83795_read(client, W83795_REG_PECI_TBASE(i)); - dev_info(&client->dev, - "PECI agent %d Tbase temperature: %u\n", - i + 1, (unsigned int)tmp & 0x7f); - } - } - - data->has_gain = w83795_read(client, W83795_REG_VMIGB_CTRL) & 0x0f; - - /* pwm and smart fan */ - if (data->chip_type == w83795g) - data->has_pwm = 8; - else - data->has_pwm = 2; - - /* Check if BEEP pin is available */ - if (data->chip_type == w83795g) { - /* The W83795G has a dedicated BEEP pin */ - data->enable_beep = 1; - } else { - /* - * The W83795ADG has a shared pin for OVT# and BEEP, so you - * can't have both - */ - tmp = w83795_read(client, W83795_REG_OVT_CFG); - if ((tmp & OVT_CFG_SEL) == 0) - data->enable_beep = 1; - } - - err = w83795_handle_files(dev, device_create_file); - if (err) - goto exit_remove; - - if (data->chip_type == w83795g) - w83795_check_dynamic_in_limits(client); - - 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: - w83795_handle_files(dev, device_remove_file_wrapper); - kfree(data); -exit: - return err; -} - -static int w83795_remove(struct i2c_client *client) -{ - struct w83795_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - w83795_handle_files(&client->dev, device_remove_file_wrapper); - kfree(data); - - return 0; -} - - -static const struct i2c_device_id w83795_id[] = { - { "w83795g", w83795g }, - { "w83795adg", w83795adg }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83795_id); - -static struct i2c_driver w83795_driver = { - .driver = { - .name = "w83795", - }, - .probe = w83795_probe, - .remove = w83795_remove, - .id_table = w83795_id, - - .class = I2C_CLASS_HWMON, - .detect = w83795_detect, - .address_list = normal_i2c, -}; - -module_i2c_driver(w83795_driver); - -MODULE_AUTHOR("Wei Song, Jean Delvare "); -MODULE_DESCRIPTION("W83795G/ADG hardware monitoring driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83l785ts.c b/ANDROID_3.4.5/drivers/hwmon/w83l785ts.c deleted file mode 100644 index 5f14e389..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83l785ts.c +++ /dev/null @@ -1,312 +0,0 @@ -/* - * w83l785ts.c - Part of lm_sensors, Linux kernel modules for hardware - * monitoring - * Copyright (C) 2003-2009 Jean Delvare - * - * Inspired from the lm83 driver. The W83L785TS-S is a sensor chip made - * by Winbond. It reports a single external temperature with a 1 deg - * resolution and a 3 deg accuracy. Datasheet can be obtained from - * Winbond's website at: - * http://www.winbond-usa.com/products/winbond_products/pdfs/PCIC/W83L785TS-S.pdf - * - * Ported to Linux 2.6 by Wolfgang Ziegler and Jean Delvare - * . - * - * Thanks to James Bolt for benchmarking the read - * error handling mechanism. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* How many retries on register read error */ -#define MAX_RETRIES 5 - -/* - * Address to scan - * Address is fully defined internally and cannot be changed. - */ - -static const unsigned short normal_i2c[] = { 0x2e, I2C_CLIENT_END }; - -/* - * The W83L785TS-S registers - * Manufacturer ID is 0x5CA3 for Winbond. - */ - -#define W83L785TS_REG_MAN_ID1 0x4D -#define W83L785TS_REG_MAN_ID2 0x4C -#define W83L785TS_REG_CHIP_ID 0x4E -#define W83L785TS_REG_CONFIG 0x40 -#define W83L785TS_REG_TYPE 0x52 -#define W83L785TS_REG_TEMP 0x27 -#define W83L785TS_REG_TEMP_OVER 0x53 /* not sure about this one */ - -/* - * Conversions - * The W83L785TS-S uses signed 8-bit values. - */ - -#define TEMP_FROM_REG(val) ((val) * 1000) - -/* - * Functions declaration - */ - -static int w83l785ts_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83l785ts_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int w83l785ts_remove(struct i2c_client *client); -static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval); -static struct w83l785ts_data *w83l785ts_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id w83l785ts_id[] = { - { "w83l785ts", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83l785ts_id); - -static struct i2c_driver w83l785ts_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83l785ts", - }, - .probe = w83l785ts_probe, - .remove = w83l785ts_remove, - .id_table = w83l785ts_id, - .detect = w83l785ts_detect, - .address_list = normal_i2c, -}; - -/* - * Client data (each client gets its own) - */ - -struct w83l785ts_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* zero until following fields are valid */ - unsigned long last_updated; /* in jiffies */ - - /* registers values */ - s8 temp[2]; /* 0: input, 1: critical limit */ -}; - -/* - * Sysfs stuff - */ - -static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct w83l785ts_data *data = w83l785ts_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[attr->index])); -} - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); -static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp, NULL, 1); - -/* - * Real code - */ - -/* Return 0 if detection is successful, -ENODEV otherwise */ -static int w83l785ts_detect(struct i2c_client *client, - struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u16 man_id; - u8 chip_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* detection */ - if ((w83l785ts_read_value(client, W83L785TS_REG_CONFIG, 0) & 0x80) - || (w83l785ts_read_value(client, W83L785TS_REG_TYPE, 0) & 0xFC)) { - dev_dbg(&adapter->dev, - "W83L785TS-S detection failed at 0x%02x\n", - client->addr); - return -ENODEV; - } - - /* Identification */ - man_id = (w83l785ts_read_value(client, W83L785TS_REG_MAN_ID1, 0) << 8) - + w83l785ts_read_value(client, W83L785TS_REG_MAN_ID2, 0); - chip_id = w83l785ts_read_value(client, W83L785TS_REG_CHIP_ID, 0); - - if (man_id != 0x5CA3 /* Winbond */ - || chip_id != 0x70) { /* W83L785TS-S */ - dev_dbg(&adapter->dev, - "Unsupported chip (man_id=0x%04X, chip_id=0x%02X)\n", - man_id, chip_id); - return -ENODEV; - } - - strlcpy(info->type, "w83l785ts", I2C_NAME_SIZE); - - return 0; -} - -static int w83l785ts_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct w83l785ts_data *data; - int err = 0; - - data = kzalloc(sizeof(struct w83l785ts_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(new_client, data); - data->valid = 0; - mutex_init(&data->update_lock); - - /* Default values in case the first read fails (unlikely). */ - data->temp[1] = data->temp[0] = 0; - - /* - * Initialize the W83L785TS chip - * Nothing yet, assume it is already started. - */ - - err = device_create_file(&new_client->dev, - &sensor_dev_attr_temp1_input.dev_attr); - if (err) - goto exit_remove; - - err = device_create_file(&new_client->dev, - &sensor_dev_attr_temp1_max.dev_attr); - if (err) - goto exit_remove; - - /* Register sysfs hooks */ - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - device_remove_file(&new_client->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_remove_file(&new_client->dev, - &sensor_dev_attr_temp1_max.dev_attr); - kfree(data); -exit: - return err; -} - -static int w83l785ts_remove(struct i2c_client *client) -{ - struct w83l785ts_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - device_remove_file(&client->dev, - &sensor_dev_attr_temp1_input.dev_attr); - device_remove_file(&client->dev, - &sensor_dev_attr_temp1_max.dev_attr); - - kfree(data); - return 0; -} - -static u8 w83l785ts_read_value(struct i2c_client *client, u8 reg, u8 defval) -{ - int value, i; - struct device *dev; - const char *prefix; - - /* - * We might be called during detection, at which point the client - * isn't yet fully initialized, so we can't use dev_dbg on it - */ - if (i2c_get_clientdata(client)) { - dev = &client->dev; - prefix = ""; - } else { - dev = &client->adapter->dev; - prefix = "w83l785ts: "; - } - - /* - * Frequent read errors have been reported on Asus boards, so we - * retry on read errors. If it still fails (unlikely), return the - * default value requested by the caller. - */ - for (i = 1; i <= MAX_RETRIES; i++) { - value = i2c_smbus_read_byte_data(client, reg); - if (value >= 0) { - dev_dbg(dev, "%sRead 0x%02x from register 0x%02x.\n", - prefix, value, reg); - return value; - } - dev_dbg(dev, "%sRead failed, will retry in %d.\n", prefix, i); - msleep(i); - } - - dev_err(dev, "%sCouldn't read value from register 0x%02x.\n", prefix, - reg); - return defval; -} - -static struct w83l785ts_data *w83l785ts_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83l785ts_data *data = i2c_get_clientdata(client); - - mutex_lock(&data->update_lock); - - if (!data->valid || time_after(jiffies, data->last_updated + HZ * 2)) { - dev_dbg(&client->dev, "Updating w83l785ts data.\n"); - data->temp[0] = w83l785ts_read_value(client, - W83L785TS_REG_TEMP, data->temp[0]); - data->temp[1] = w83l785ts_read_value(client, - W83L785TS_REG_TEMP_OVER, data->temp[1]); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(w83l785ts_driver); - -MODULE_AUTHOR("Jean Delvare "); -MODULE_DESCRIPTION("W83L785TS-S driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/w83l786ng.c b/ANDROID_3.4.5/drivers/hwmon/w83l786ng.c deleted file mode 100644 index 5850b770..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/w83l786ng.c +++ /dev/null @@ -1,817 +0,0 @@ -/* - * w83l786ng.c - Linux kernel driver for hardware monitoring - * Copyright (c) 2007 Kevin Lo - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation - version 2. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA. - */ - -/* - * Supports following chips: - * - * Chip #vin #fanin #pwm #temp wchipid vendid i2c ISA - * w83l786ng 3 2 2 2 0x7b 0x5ca3 yes no - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Addresses to scan */ -static const unsigned short normal_i2c[] = { 0x2e, 0x2f, I2C_CLIENT_END }; - -/* Insmod parameters */ - -static bool reset; -module_param(reset, bool, 0); -MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended"); - -#define W83L786NG_REG_IN_MIN(nr) (0x2C + (nr) * 2) -#define W83L786NG_REG_IN_MAX(nr) (0x2B + (nr) * 2) -#define W83L786NG_REG_IN(nr) ((nr) + 0x20) - -#define W83L786NG_REG_FAN(nr) ((nr) + 0x28) -#define W83L786NG_REG_FAN_MIN(nr) ((nr) + 0x3B) - -#define W83L786NG_REG_CONFIG 0x40 -#define W83L786NG_REG_ALARM1 0x41 -#define W83L786NG_REG_ALARM2 0x42 -#define W83L786NG_REG_GPIO_EN 0x47 -#define W83L786NG_REG_MAN_ID2 0x4C -#define W83L786NG_REG_MAN_ID1 0x4D -#define W83L786NG_REG_CHIP_ID 0x4E - -#define W83L786NG_REG_DIODE 0x53 -#define W83L786NG_REG_FAN_DIV 0x54 -#define W83L786NG_REG_FAN_CFG 0x80 - -#define W83L786NG_REG_TOLERANCE 0x8D - -static const u8 W83L786NG_REG_TEMP[2][3] = { - { 0x25, /* TEMP 0 in DataSheet */ - 0x35, /* TEMP 0 Over in DataSheet */ - 0x36 }, /* TEMP 0 Hyst in DataSheet */ - { 0x26, /* TEMP 1 in DataSheet */ - 0x37, /* TEMP 1 Over in DataSheet */ - 0x38 } /* TEMP 1 Hyst in DataSheet */ -}; - -static const u8 W83L786NG_PWM_MODE_SHIFT[] = {6, 7}; -static const u8 W83L786NG_PWM_ENABLE_SHIFT[] = {2, 4}; - -/* FAN Duty Cycle, be used to control */ -static const u8 W83L786NG_REG_PWM[] = {0x81, 0x87}; - - -static inline u8 -FAN_TO_REG(long rpm, int div) -{ - if (rpm == 0) - return 255; - rpm = SENSORS_LIMIT(rpm, 1, 1000000); - return SENSORS_LIMIT((1350000 + rpm * div / 2) / (rpm * div), 1, 254); -} - -#define FAN_FROM_REG(val, div) ((val) == 0 ? -1 : \ - ((val) == 255 ? 0 : \ - 1350000 / ((val) * (div)))) - -/* for temp */ -#define TEMP_TO_REG(val) (SENSORS_LIMIT(((val) < 0 ? \ - (val) + 0x100 * 1000 \ - : (val)) / 1000, 0, 0xff)) -#define TEMP_FROM_REG(val) (((val) & 0x80 ? \ - (val) - 0x100 : (val)) * 1000) - -/* - * The analog voltage inputs have 8mV LSB. Since the sysfs output is - * in mV as would be measured on the chip input pin, need to just - * multiply/divide by 8 to translate from/to register values. - */ -#define IN_TO_REG(val) (SENSORS_LIMIT((((val) + 4) / 8), 0, 255)) -#define IN_FROM_REG(val) ((val) * 8) - -#define DIV_FROM_REG(val) (1 << (val)) - -static inline u8 -DIV_TO_REG(long val) -{ - int i; - val = SENSORS_LIMIT(val, 1, 128) >> 1; - for (i = 0; i < 7; i++) { - if (val == 0) - break; - val >>= 1; - } - return (u8)i; -} - -struct w83l786ng_data { - struct device *hwmon_dev; - struct mutex update_lock; - char valid; /* !=0 if following fields are valid */ - unsigned long last_updated; /* In jiffies */ - unsigned long last_nonvolatile; /* In jiffies, last time we update the - * nonvolatile registers */ - - u8 in[3]; - u8 in_max[3]; - u8 in_min[3]; - u8 fan[2]; - u8 fan_div[2]; - u8 fan_min[2]; - u8 temp_type[2]; - u8 temp[2][3]; - u8 pwm[2]; - u8 pwm_mode[2]; /* 0->DC variable voltage - * 1->PWM variable duty cycle */ - - u8 pwm_enable[2]; /* 1->manual - * 2->thermal cruise (also called SmartFan I) */ - u8 tolerance[2]; -}; - -static int w83l786ng_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83l786ng_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int w83l786ng_remove(struct i2c_client *client); -static void w83l786ng_init_client(struct i2c_client *client); -static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); - -static const struct i2c_device_id w83l786ng_id[] = { - { "w83l786ng", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83l786ng_id); - -static struct i2c_driver w83l786ng_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83l786ng", - }, - .probe = w83l786ng_probe, - .remove = w83l786ng_remove, - .id_table = w83l786ng_id, - .detect = w83l786ng_detect, - .address_list = normal_i2c, -}; - -static u8 -w83l786ng_read_value(struct i2c_client *client, u8 reg) -{ - return i2c_smbus_read_byte_data(client, reg); -} - -static int -w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value) -{ - return i2c_smbus_write_byte_data(client, reg, value); -} - -/* following are the sysfs callback functions */ -#define show_in_reg(reg) \ -static ssize_t \ -show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct w83l786ng_data *data = w83l786ng_update_device(dev); \ - return sprintf(buf, "%d\n", IN_FROM_REG(data->reg[nr])); \ -} - -show_in_reg(in) -show_in_reg(in_min) -show_in_reg(in_max) - -#define store_in_reg(REG, reg) \ -static ssize_t \ -store_in_##reg(struct device *dev, struct device_attribute *attr, \ - const char *buf, size_t count) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83l786ng_data *data = i2c_get_clientdata(client); \ - unsigned long val; \ - int err = kstrtoul(buf, 10, &val); \ - if (err) \ - return err; \ - mutex_lock(&data->update_lock); \ - data->in_##reg[nr] = IN_TO_REG(val); \ - w83l786ng_write_value(client, W83L786NG_REG_IN_##REG(nr), \ - data->in_##reg[nr]); \ - mutex_unlock(&data->update_lock); \ - return count; \ -} - -store_in_reg(MIN, min) -store_in_reg(MAX, max) - -static struct sensor_device_attribute sda_in_input[] = { - SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0), - SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1), - SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2), -}; - -static struct sensor_device_attribute sda_in_min[] = { - SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0), - SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1), - SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2), -}; - -static struct sensor_device_attribute sda_in_max[] = { - SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0), - SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1), - SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2), -}; - -#define show_fan_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - int nr = to_sensor_dev_attr(attr)->index; \ - struct w83l786ng_data *data = w83l786ng_update_device(dev); \ - return sprintf(buf, "%d\n", \ - FAN_FROM_REG(data->fan[nr], DIV_FROM_REG(data->fan_div[nr]))); \ -} - -show_fan_reg(fan); -show_fan_reg(fan_min); - -static ssize_t -store_fan_min(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr])); - w83l786ng_write_value(client, W83L786NG_REG_FAN_MIN(nr), - data->fan_min[nr]); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t -show_fan_div(struct device *dev, struct device_attribute *attr, - char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct w83l786ng_data *data = w83l786ng_update_device(dev); - return sprintf(buf, "%u\n", DIV_FROM_REG(data->fan_div[nr])); -} - -/* - * Note: we save and restore the fan minimum here, because its value is - * determined in part by the fan divisor. This follows the principle of - * least surprise; the user doesn't expect the fan minimum to change just - * because the divisor changed. - */ -static ssize_t -store_fan_div(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - - unsigned long min; - u8 tmp_fan_div; - u8 fan_div_reg; - u8 keep_mask = 0; - u8 new_shift = 0; - - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - /* Save fan_min */ - mutex_lock(&data->update_lock); - min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])); - - data->fan_div[nr] = DIV_TO_REG(val); - - switch (nr) { - case 0: - keep_mask = 0xf8; - new_shift = 0; - break; - case 1: - keep_mask = 0x8f; - new_shift = 4; - break; - } - - fan_div_reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV) - & keep_mask; - - tmp_fan_div = (data->fan_div[nr] << new_shift) & ~keep_mask; - - w83l786ng_write_value(client, W83L786NG_REG_FAN_DIV, - fan_div_reg | tmp_fan_div); - - /* Restore fan_min */ - data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr])); - w83l786ng_write_value(client, W83L786NG_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), -}; - -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), -}; - -static struct sensor_device_attribute sda_fan_div[] = { - SENSOR_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div, - store_fan_div, 0), - SENSOR_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div, - store_fan_div, 1), -}; - - -/* read/write the temperature, includes measured value and limits */ - -static ssize_t -show_temp(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct w83l786ng_data *data = w83l786ng_update_device(dev); - return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp[nr][index])); -} - -static ssize_t -store_temp(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct sensor_device_attribute_2 *sensor_attr = - to_sensor_dev_attr_2(attr); - int nr = sensor_attr->nr; - int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->temp[nr][index] = TEMP_TO_REG(val); - w83l786ng_write_value(client, W83L786NG_REG_TEMP[nr][index], - data->temp[nr][index]); - 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), -}; - -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), -}; - -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), -}; - -#define show_pwm_reg(reg) \ -static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \ - char *buf) \ -{ \ - struct w83l786ng_data *data = w83l786ng_update_device(dev); \ - int nr = to_sensor_dev_attr(attr)->index; \ - return sprintf(buf, "%d\n", data->reg[nr]); \ -} - -show_pwm_reg(pwm_mode) -show_pwm_reg(pwm_enable) -show_pwm_reg(pwm) - -static ssize_t -store_pwm_mode(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (val > 1) - return -EINVAL; - mutex_lock(&data->update_lock); - data->pwm_mode[nr] = val; - reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); - reg &= ~(1 << W83L786NG_PWM_MODE_SHIFT[nr]); - if (!val) - reg |= 1 << W83L786NG_PWM_MODE_SHIFT[nr]; - w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_pwm(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - val = SENSORS_LIMIT(val, 0, 255); - - mutex_lock(&data->update_lock); - data->pwm[nr] = val; - w83l786ng_write_value(client, W83L786NG_REG_PWM[nr], val); - mutex_unlock(&data->update_lock); - return count; -} - -static ssize_t -store_pwm_enable(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - u8 reg; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - if (!val || val > 2) /* only modes 1 and 2 are supported */ - return -EINVAL; - - mutex_lock(&data->update_lock); - reg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); - data->pwm_enable[nr] = val; - reg &= ~(0x02 << W83L786NG_PWM_ENABLE_SHIFT[nr]); - reg |= (val - 1) << W83L786NG_PWM_ENABLE_SHIFT[nr]; - w83l786ng_write_value(client, W83L786NG_REG_FAN_CFG, reg); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute sda_pwm[] = { - SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0), - SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1), -}; - -static struct sensor_device_attribute sda_pwm_mode[] = { - SENSOR_ATTR(pwm1_mode, S_IWUSR | S_IRUGO, show_pwm_mode, - store_pwm_mode, 0), - SENSOR_ATTR(pwm2_mode, S_IWUSR | S_IRUGO, show_pwm_mode, - store_pwm_mode, 1), -}; - -static struct sensor_device_attribute sda_pwm_enable[] = { - SENSOR_ATTR(pwm1_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 0), - SENSOR_ATTR(pwm2_enable, S_IWUSR | S_IRUGO, show_pwm_enable, - store_pwm_enable, 1), -}; - -/* For Smart Fan I/Thermal Cruise and Smart Fan II */ -static ssize_t -show_tolerance(struct device *dev, struct device_attribute *attr, char *buf) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct w83l786ng_data *data = w83l786ng_update_device(dev); - return sprintf(buf, "%ld\n", (long)data->tolerance[nr]); -} - -static ssize_t -store_tolerance(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - u8 tol_tmp, tol_mask; - unsigned long val; - int err; - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - tol_mask = w83l786ng_read_value(client, - W83L786NG_REG_TOLERANCE) & ((nr == 1) ? 0x0f : 0xf0); - tol_tmp = SENSORS_LIMIT(val, 0, 15); - tol_tmp &= 0x0f; - data->tolerance[nr] = tol_tmp; - if (nr == 1) - tol_tmp <<= 4; - - w83l786ng_write_value(client, W83L786NG_REG_TOLERANCE, - tol_mask | tol_tmp); - mutex_unlock(&data->update_lock); - return count; -} - -static struct sensor_device_attribute sda_tolerance[] = { - SENSOR_ATTR(pwm1_tolerance, S_IWUSR | S_IRUGO, - show_tolerance, store_tolerance, 0), - SENSOR_ATTR(pwm2_tolerance, S_IWUSR | S_IRUGO, - show_tolerance, store_tolerance, 1), -}; - - -#define IN_UNIT_ATTRS(X) \ - &sda_in_input[X].dev_attr.attr, \ - &sda_in_min[X].dev_attr.attr, \ - &sda_in_max[X].dev_attr.attr - -#define FAN_UNIT_ATTRS(X) \ - &sda_fan_input[X].dev_attr.attr, \ - &sda_fan_min[X].dev_attr.attr, \ - &sda_fan_div[X].dev_attr.attr - -#define TEMP_UNIT_ATTRS(X) \ - &sda_temp_input[X].dev_attr.attr, \ - &sda_temp_max[X].dev_attr.attr, \ - &sda_temp_max_hyst[X].dev_attr.attr - -#define PWM_UNIT_ATTRS(X) \ - &sda_pwm[X].dev_attr.attr, \ - &sda_pwm_mode[X].dev_attr.attr, \ - &sda_pwm_enable[X].dev_attr.attr - -#define TOLERANCE_UNIT_ATTRS(X) \ - &sda_tolerance[X].dev_attr.attr - -static struct attribute *w83l786ng_attributes[] = { - IN_UNIT_ATTRS(0), - IN_UNIT_ATTRS(1), - IN_UNIT_ATTRS(2), - FAN_UNIT_ATTRS(0), - FAN_UNIT_ATTRS(1), - TEMP_UNIT_ATTRS(0), - TEMP_UNIT_ATTRS(1), - PWM_UNIT_ATTRS(0), - PWM_UNIT_ATTRS(1), - TOLERANCE_UNIT_ATTRS(0), - TOLERANCE_UNIT_ATTRS(1), - NULL -}; - -static const struct attribute_group w83l786ng_group = { - .attrs = w83l786ng_attributes, -}; - -static int -w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info) -{ - struct i2c_adapter *adapter = client->adapter; - u16 man_id; - u8 chip_id; - - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -ENODEV; - - /* Detection */ - if ((w83l786ng_read_value(client, W83L786NG_REG_CONFIG) & 0x80)) { - dev_dbg(&adapter->dev, "W83L786NG detection failed at 0x%02x\n", - client->addr); - return -ENODEV; - } - - /* Identification */ - man_id = (w83l786ng_read_value(client, W83L786NG_REG_MAN_ID1) << 8) + - w83l786ng_read_value(client, W83L786NG_REG_MAN_ID2); - chip_id = w83l786ng_read_value(client, W83L786NG_REG_CHIP_ID); - - if (man_id != 0x5CA3 || /* Winbond */ - chip_id != 0x80) { /* W83L786NG */ - dev_dbg(&adapter->dev, - "Unsupported chip (man_id=0x%04X, chip_id=0x%02X)\n", - man_id, chip_id); - return -ENODEV; - } - - strlcpy(info->type, "w83l786ng", I2C_NAME_SIZE); - - return 0; -} - -static int -w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - struct device *dev = &client->dev; - struct w83l786ng_data *data; - int i, err = 0; - u8 reg_tmp; - - data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the chip */ - w83l786ng_init_client(client); - - /* A few vars need to be filled upon startup */ - for (i = 0; i < 2; i++) { - data->fan_min[i] = w83l786ng_read_value(client, - W83L786NG_REG_FAN_MIN(i)); - } - - /* Update the fan divisor */ - reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV); - data->fan_div[0] = reg_tmp & 0x07; - data->fan_div[1] = (reg_tmp >> 4) & 0x07; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group); - 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; - - /* Unregister sysfs hooks */ - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); - kfree(data); -exit: - return err; -} - -static int -w83l786ng_remove(struct i2c_client *client) -{ - struct w83l786ng_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); - - kfree(data); - - return 0; -} - -static void -w83l786ng_init_client(struct i2c_client *client) -{ - u8 tmp; - - if (reset) - w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80); - - /* Start monitoring */ - tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG); - if (!(tmp & 0x01)) - w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01); -} - -static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - int i, j; - u8 reg_tmp, pwmcfg; - - mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - dev_dbg(&client->dev, "Updating w83l786ng data.\n"); - - /* Update the voltages measured value and limits */ - for (i = 0; i < 3; i++) { - data->in[i] = w83l786ng_read_value(client, - W83L786NG_REG_IN(i)); - data->in_min[i] = w83l786ng_read_value(client, - W83L786NG_REG_IN_MIN(i)); - data->in_max[i] = w83l786ng_read_value(client, - W83L786NG_REG_IN_MAX(i)); - } - - /* Update the fan counts and limits */ - for (i = 0; i < 2; i++) { - data->fan[i] = w83l786ng_read_value(client, - W83L786NG_REG_FAN(i)); - data->fan_min[i] = w83l786ng_read_value(client, - W83L786NG_REG_FAN_MIN(i)); - } - - /* Update the fan divisor */ - reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV); - data->fan_div[0] = reg_tmp & 0x07; - data->fan_div[1] = (reg_tmp >> 4) & 0x07; - - pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); - for (i = 0; i < 2; i++) { - data->pwm_mode[i] = - ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1) - ? 0 : 1; - data->pwm_enable[i] = - ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 2) + 1; - data->pwm[i] = w83l786ng_read_value(client, - W83L786NG_REG_PWM[i]); - } - - - /* Update the temperature sensors */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - data->temp[i][j] = w83l786ng_read_value(client, - W83L786NG_REG_TEMP[i][j]); - } - } - - /* Update Smart Fan I/II tolerance */ - reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE); - data->tolerance[0] = reg_tmp & 0x0f; - data->tolerance[1] = (reg_tmp >> 4) & 0x0f; - - data->last_updated = jiffies; - data->valid = 1; - - } - - mutex_unlock(&data->update_lock); - - return data; -} - -module_i2c_driver(w83l786ng_driver); - -MODULE_AUTHOR("Kevin Lo"); -MODULE_DESCRIPTION("w83l786ng driver"); -MODULE_LICENSE("GPL"); diff --git a/ANDROID_3.4.5/drivers/hwmon/wm831x-hwmon.c b/ANDROID_3.4.5/drivers/hwmon/wm831x-hwmon.c deleted file mode 100644 index 07cb25ae..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/wm831x-hwmon.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * drivers/hwmon/wm831x-hwmon.c - Wolfson Microelectronics WM831x PMIC - * hardware monitoring features. - * - * Copyright (C) 2009 Wolfson Microelectronics plc - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -struct wm831x_hwmon { - struct wm831x *wm831x; - struct device *classdev; -}; - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "wm831x\n"); -} - -static const char * const input_names[] = { - [WM831X_AUX_SYSVDD] = "SYSVDD", - [WM831X_AUX_USB] = "USB", - [WM831X_AUX_BKUP_BATT] = "Backup battery", - [WM831X_AUX_BATT] = "Battery", - [WM831X_AUX_WALL] = "WALL", - [WM831X_AUX_CHIP_TEMP] = "PMIC", - [WM831X_AUX_BATT_TEMP] = "Battery", -}; - - -static ssize_t show_voltage(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct wm831x_hwmon *hwmon = dev_get_drvdata(dev); - int channel = to_sensor_dev_attr(attr)->index; - int ret; - - ret = wm831x_auxadc_read_uv(hwmon->wm831x, channel); - if (ret < 0) - return ret; - - return sprintf(buf, "%d\n", DIV_ROUND_CLOSEST(ret, 1000)); -} - -static ssize_t show_chip_temp(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct wm831x_hwmon *hwmon = dev_get_drvdata(dev); - int channel = to_sensor_dev_attr(attr)->index; - int ret; - - ret = wm831x_auxadc_read(hwmon->wm831x, channel); - if (ret < 0) - return ret; - - /* Degrees celsius = (512.18-ret) / 1.0983 */ - ret = 512180 - (ret * 1000); - ret = DIV_ROUND_CLOSEST(ret * 10000, 10983); - - return sprintf(buf, "%d\n", ret); -} - -static ssize_t show_label(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int channel = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%s\n", input_names[channel]); -} - -#define WM831X_VOLTAGE(id, name) \ - static SENSOR_DEVICE_ATTR(in##id##_input, S_IRUGO, show_voltage, \ - NULL, name) - -#define WM831X_NAMED_VOLTAGE(id, name) \ - WM831X_VOLTAGE(id, name); \ - static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \ - NULL, name) - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -WM831X_VOLTAGE(0, WM831X_AUX_AUX1); -WM831X_VOLTAGE(1, WM831X_AUX_AUX2); -WM831X_VOLTAGE(2, WM831X_AUX_AUX3); -WM831X_VOLTAGE(3, WM831X_AUX_AUX4); - -WM831X_NAMED_VOLTAGE(4, WM831X_AUX_SYSVDD); -WM831X_NAMED_VOLTAGE(5, WM831X_AUX_USB); -WM831X_NAMED_VOLTAGE(6, WM831X_AUX_BATT); -WM831X_NAMED_VOLTAGE(7, WM831X_AUX_WALL); -WM831X_NAMED_VOLTAGE(8, WM831X_AUX_BKUP_BATT); - -static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_chip_temp, NULL, - WM831X_AUX_CHIP_TEMP); -static SENSOR_DEVICE_ATTR(temp1_label, S_IRUGO, show_label, NULL, - WM831X_AUX_CHIP_TEMP); -/* - * Report as a voltage since conversion depends on external components - * and that's what the ABI wants. - */ -static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_voltage, NULL, - WM831X_AUX_BATT_TEMP); -static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, - WM831X_AUX_BATT_TEMP); - -static struct attribute *wm831x_attributes[] = { - &dev_attr_name.attr, - - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in3_input.dev_attr.attr, - - &sensor_dev_attr_in4_input.dev_attr.attr, - &sensor_dev_attr_in4_label.dev_attr.attr, - &sensor_dev_attr_in5_input.dev_attr.attr, - &sensor_dev_attr_in5_label.dev_attr.attr, - &sensor_dev_attr_in6_input.dev_attr.attr, - &sensor_dev_attr_in6_label.dev_attr.attr, - &sensor_dev_attr_in7_input.dev_attr.attr, - &sensor_dev_attr_in7_label.dev_attr.attr, - &sensor_dev_attr_in8_input.dev_attr.attr, - &sensor_dev_attr_in8_label.dev_attr.attr, - - &sensor_dev_attr_temp1_input.dev_attr.attr, - &sensor_dev_attr_temp1_label.dev_attr.attr, - &sensor_dev_attr_temp2_input.dev_attr.attr, - &sensor_dev_attr_temp2_label.dev_attr.attr, - - NULL -}; - -static const struct attribute_group wm831x_attr_group = { - .attrs = wm831x_attributes, -}; - -static int __devinit wm831x_hwmon_probe(struct platform_device *pdev) -{ - struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_hwmon *hwmon; - int ret; - - hwmon = kzalloc(sizeof(struct wm831x_hwmon), GFP_KERNEL); - if (!hwmon) - return -ENOMEM; - - hwmon->wm831x = wm831x; - - ret = sysfs_create_group(&pdev->dev.kobj, &wm831x_attr_group); - if (ret) - goto err; - - hwmon->classdev = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon->classdev)) { - ret = PTR_ERR(hwmon->classdev); - goto err_sysfs; - } - - platform_set_drvdata(pdev, hwmon); - - return 0; - -err_sysfs: - sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group); -err: - kfree(hwmon); - return ret; -} - -static int __devexit wm831x_hwmon_remove(struct platform_device *pdev) -{ - struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev); - - hwmon_device_unregister(hwmon->classdev); - sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group); - platform_set_drvdata(pdev, NULL); - kfree(hwmon); - - return 0; -} - -static struct platform_driver wm831x_hwmon_driver = { - .probe = wm831x_hwmon_probe, - .remove = __devexit_p(wm831x_hwmon_remove), - .driver = { - .name = "wm831x-hwmon", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(wm831x_hwmon_driver); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("WM831x Hardware Monitoring"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm831x-hwmon"); diff --git a/ANDROID_3.4.5/drivers/hwmon/wm8350-hwmon.c b/ANDROID_3.4.5/drivers/hwmon/wm8350-hwmon.c deleted file mode 100644 index b955756b..00000000 --- a/ANDROID_3.4.5/drivers/hwmon/wm8350-hwmon.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * drivers/hwmon/wm8350-hwmon.c - Wolfson Microelectronics WM8350 PMIC - * hardware monitoring features. - * - * Copyright (C) 2009 Wolfson Microelectronics plc - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License v2 as published by the - * Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include -#include -#include -#include -#include -#include - -#include -#include - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "wm8350\n"); -} - -static const char * const input_names[] = { - [WM8350_AUXADC_USB] = "USB", - [WM8350_AUXADC_LINE] = "Line", - [WM8350_AUXADC_BATT] = "Battery", -}; - - -static ssize_t show_voltage(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct wm8350 *wm8350 = dev_get_drvdata(dev); - int channel = to_sensor_dev_attr(attr)->index; - int val; - - val = wm8350_read_auxadc(wm8350, channel, 0, 0) * WM8350_AUX_COEFF; - val = DIV_ROUND_CLOSEST(val, 1000); - - return sprintf(buf, "%d\n", val); -} - -static ssize_t show_label(struct device *dev, - struct device_attribute *attr, char *buf) -{ - int channel = to_sensor_dev_attr(attr)->index; - - return sprintf(buf, "%s\n", input_names[channel]); -} - -#define WM8350_NAMED_VOLTAGE(id, name) \ - static SENSOR_DEVICE_ATTR(in##id##_input, S_IRUGO, show_voltage,\ - NULL, name); \ - static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \ - NULL, name) - -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - -WM8350_NAMED_VOLTAGE(0, WM8350_AUXADC_USB); -WM8350_NAMED_VOLTAGE(1, WM8350_AUXADC_BATT); -WM8350_NAMED_VOLTAGE(2, WM8350_AUXADC_LINE); - -static struct attribute *wm8350_attributes[] = { - &dev_attr_name.attr, - - &sensor_dev_attr_in0_input.dev_attr.attr, - &sensor_dev_attr_in0_label.dev_attr.attr, - &sensor_dev_attr_in1_input.dev_attr.attr, - &sensor_dev_attr_in1_label.dev_attr.attr, - &sensor_dev_attr_in2_input.dev_attr.attr, - &sensor_dev_attr_in2_label.dev_attr.attr, - - NULL, -}; - -static const struct attribute_group wm8350_attr_group = { - .attrs = wm8350_attributes, -}; - -static int __devinit wm8350_hwmon_probe(struct platform_device *pdev) -{ - struct wm8350 *wm8350 = platform_get_drvdata(pdev); - int ret; - - ret = sysfs_create_group(&pdev->dev.kobj, &wm8350_attr_group); - if (ret) - goto err; - - wm8350->hwmon.classdev = hwmon_device_register(&pdev->dev); - if (IS_ERR(wm8350->hwmon.classdev)) { - ret = PTR_ERR(wm8350->hwmon.classdev); - goto err_group; - } - - return 0; - -err_group: - sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group); -err: - return ret; -} - -static int __devexit wm8350_hwmon_remove(struct platform_device *pdev) -{ - struct wm8350 *wm8350 = platform_get_drvdata(pdev); - - hwmon_device_unregister(wm8350->hwmon.classdev); - sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group); - - return 0; -} - -static struct platform_driver wm8350_hwmon_driver = { - .probe = wm8350_hwmon_probe, - .remove = __devexit_p(wm8350_hwmon_remove), - .driver = { - .name = "wm8350-hwmon", - .owner = THIS_MODULE, - }, -}; - -module_platform_driver(wm8350_hwmon_driver); - -MODULE_AUTHOR("Mark Brown "); -MODULE_DESCRIPTION("WM8350 Hardware Monitoring"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:wm8350-hwmon"); -- cgit