hwmon changes for v3.4

Mostly cleanup. No new drivers this time around, but support for several chips
 added to existing drivers: TPS40400, TPS40422, MTD040, MAX34446, ZL9101M,
 ZL9117M, and LM96080. Also, added watchdog support for SCH56xx, and additional
 attributes for a couple of drivers.
 
 312869e hwmon: (sch56xx) Add support for the integrated watchdog (v2)
 840e191 hwmon: (w83627ehf) Add support for temperature offset registers
 86dda17 hwmon: (jc42) Remove unnecessary device IDs
 3360a10 hwmon: (zl6100) Add support for ZL9101M and ZL9117M
 9271126 hwmon: (adm1275) Add support for ADM1075
 590defe hwmon: (max34440) Add support for MAX34446
 60b873e hwmon: (pmbus) Add more virtual registers
 2163340 hwmon: (pmbus) Add support for Lineage Power MDT040
 c5f35c9 hwmon: (pmbus) Add support for TI TPS40400 and TPS40422
 56aad5d hwmon: (max34440) Add support for 'lowest' output voltage attribute
 f15df57 hwmon: (jc42) Convert to use devm_kzalloc
 918ddef hwmon: (max16065) Convert to use devm_kzalloc
 b8a5a7c hwmon: (smm665) Convert to use devm_kzalloc
 3683928 hwmon: (ltc4261) Convert to use devm_kzalloc
 dd285ad hwmon: (pmbus) Simplify remove functions
 8b313ca hwmon: (pmbus) Convert pmbus drivers to use devm_kzalloc
 07404aa hwmon: (lineage-pem) Convert to use devm_kzalloc
 f352df6 hwmon: (hwmon-vid) Fix checkpatch issues
 3230f70 hwmon: (hwmon-vid) Add new entries to VRM model table
 9908ad4 hwmon: (lm80) Add detection of NatSemi/TI LM96080
 0e190b7 hwmon: (lm87) Get rid of macro-generated functions
 8652a26 hwmon: (lm87) Reorganize the code
 0fc86ec hwmon: (applesmc) Silence uninitialized warnings
 7599d32 hwmon: (lm70) Fix: do not use assignment in if condition
 e200c14 hwmon: (lm70) Register hwmon device after creating attribute files, and remove it first
 01d9def hwmon: (w83l786ng) Fix multi-line comments
 130067d hwmon: (w83l785ts) Fix multi-line comments
 7950133 hwmon: (w83781d) Fix: do not use assignment in if condition
 aff6e00 hwmon: (w83781d) Fix multi-line comments
 2a52dd6 hwmon: (smsc47b397) Fix multi-line comments
 36564ef hwmon: (pc87427) Fix multi-line comments
 b6707b7 hwmon: (max1668) Fix multi-line comments
 1160631 hwmon: (lm80) Fix multi-line comments
 bf0f3a0 hwmon: (emc2103) Fix multi-line comments
 fbb6670 hwmon: (adm1031) Fix multi-line comments
 94b991d hwmon: (adm1029) Fix multi-line comments
 27b9de3 hwmon: (w83627hf) Fix checkpatch issues
 ca3ccad hwmon: (w83l786ng) Fix checkpatch issues
 47efe87 hwmon: (w83793) Fix checkpatch issues
 d174368 hwmon: (w83792d) Fix checkpatch issues
 2185696 hwmon: (vt1211) Fix: do not use assignment in if condition
 b162c03 hwmon: (vt1211) Fix checkpatch issues
 9004ac8 hwmon: (via686a) Fix checkpatch issues
 bce2778 hwmon: (pc87360) Fix: do not use assignment in if condition
 449a7a0 hwmon: (pc87360) Fix checkpatch issues
 8958dfb hwmon: (max1619): Fix checkpatch issues
 09770b2 hwmon: (lm85) Fix checkpatch issues
 9b03079 hwmon: (lm78) Fix checkpatch issues
 02fe2fd hwmon: (lm77) Fix checkpatch issues
 f445a9a hwmon: (gl520sm) Fix: do not use assignment in if condition
 43da3d1 hwmon: (gl520sm) Fix checkpatch issues
 228f8e0 hwmon: (gl518sm) Fix checkpatch issues
 c8de836 hwmon: (dme1737) Fix checkpatch issues
 8c10369 hwmon: (asb100): Fix checkpatch issues
 c387e4e hwmon: (adm9240) Fix checkpatch issues
 86aa3e2 hwmon: (adm1026) Fix checkpatch issues
 21d2a8f hwmon: (adm1021) Fix checkpatch issues
 1bd385d hwmon: (abituguru) Fix checkpatch issues
 8969e84 hwmon: (w83627ehf) Fix multi-line comments
 51683ee hwmon: (max1111) Fix multi-line comments
 1b05d22 hwmon: (ltc4151) Fix multi-line comments
 1b9c491 hwmon: (g760a) Fix multi-line comments
 20eaf72 hwmon: (f71882fg) Fix multi-line comments
 4bebced hwmon: (emc1403) Fix multi-line comments
 ca3c7b6 hwmon: (amc6821) Fix multi-line comments
 10775d1 hwmon: (ads7871) Fix multi-line comments
 d13d623 hwmon: (ads7828) Fix multi-line comments
 562fca2 hwmon: (abituguru3) Fix multi-line comments
 ec1c319 hwmon: (w83791d) Fix checkpatch issues
 a80b10c hwmon: (ultra45_env) Fix checkpatch issues
 4d387df hwmon: (thmc50) Fix checkpatch issues
 85a0c0d hwmon: (smsc47m1) Fix checkpatch issues
 7e61268 hwmon: (smsc47m1) Fix: do not use assignment in if condition
 7cc3cb6 hwmon: (smsc47m192) Fix checkpatch issues
 8fda79e hwmon: (sis5595) Fix checkpatch issues
 5725608 hwmon: (pcf8591) Fix checkpatch issues
 2804a4c hwmon: (lm93) Fix checkpatch issues
 a318afd hwmon: (lm92) Fix checkpatch issues
 073f1e6c hwmon: (lm87) Fix: do not use assignment in if condition
 c6370db hwmon: (lm87) Fix checkpatch issues
 525ad37 hwmon: (fschmd) Fix checkpatch issues
 f24d548 hwmon: (atxp1) Fix checkpatch issues
 724cc33 hwmon: (adt7462) Fix checkpatch issues
 790fa38 hwmon: (ltc4215) Fix multi-line comments
 430b4fc hwmon: (ltc4245) Fix multi-line comments
 a68abd3 hwmon: (wm8350-hwmon) Constify fixed string array
 85ebfd3 hwmon: (applesmc) Fix multi-line comments
 75bdc93 hwmon: (asus_atk0110) Fix multi-line comments
 3c4c497 hwmon: (it87) Constify fixed string arrays
 8deeac8 hwmon: (ad7414) Fix multi-line comments
 5d577db hwmon: (jc42) Fix multi-line comments
 780affe hwmon: (coretemp) Fix checkpatch error
 3af2861 hwmon: (pc87360) Fix multi-line comments
 07de3df hwmon: (wm831x-hwmon) Fix multi-line comments
 3c22e23 hwmon: (smm665) Fix checkpatch error
 3c56b06 hwmon: (asc7621) Fix multi-line comments
 4a0d71c hwmon: (it87) Fix multi-line comments
 86d566e hwmon: (hwmon-vid) Fix multi-line comments
 5ed0488 hwmon: (hwmon) Fix multi-line comments
 19f2c05 hwmon: (ds1621) Fix checkpatch issues
 91efffe hwmon: convert drivers/hwmon/* to use module_spi_driver()
 f0967ee hwmon: convert drivers/hwmon/* to use module_i2c_driver()
 61ba031 hwmon: (vt8231) Fix multi-line comments
 9ed5bc2 hwmon: (adt7475) Fix multi-line comments
 2fff084 hwmon: (f71805f) Fix checkpatch issues
 703af96 hwmon: (max6650) Fix multi-line comments
 c531eb3 hwmon: (w83781d) Fix checkpatch issues
 2b22de5 hwmon: (adm1025) Fix checkpatch issues
 7973841 hwmon: (abituguru3) Fix checkpatch issues
 65fe5c7 hwmon: (vt8231) Fix checkpatch issues
 bafda5d hwmon: (max6650) Fix checkpatch issues
 0117c3f hwmon: (pmbus) Replace strict_strtol with kstrtol
 b3789a0 hwmon: (lm83) fix checkpatch issues
 93092a6 hwmon: (k8temp) fix checkpatch issues
 96585f1 hwmon: (lm80) reset device if error occurred
 6a9e7c4c hwmon: (lm80) fix checkpatch warnings
 6b904b6 hwmon: (adt7470) fix checkpatch issues
 e6a83db hwmon: (adt7411) fix checkpatch issues
 56c24af hwmon: (lm70) fix checkpatch issues
 1dc3708 hwmon: (f71882fg) fix checkpatch issues
 c6e8ac0 hwmon: (asus_atk0110) fix checkpatch issues
 99b8c83 hwmon: (adt7475) fix checkpatch issues
 b2ae8f8 hwmon: (smm665) fix checkpatch issues
 c9e1498 hwmon: (sht15) fix checkpatch issues
 0910b28 hwmon: (ibmaem) fix checkpatch issues
 dcb7cb9 hwmon: (ad7414) fix checkpatch issues
 e91aef2 hwmon: (ad7418) fix checkpatch issues
 5996542 hwmon: (w83l785ts) fix checkpatch issues
 a6100f6 hwmon: (wm831x-hwmon) fix checkpatch issues
 839a9ee hwmon: fix checkpatch issues
 08f5090 hwmon: (adm1029) fix checkpatch issues
 4d7c5d4 hwmon: (g760a) fix checkpatch issues
 7b102ed hwmon: (i5k_amb) fix checkpatch issues
 600151b hwmon: use DEFINE_PCI_DEVICE_TABLE
 7fe83ad hwmon: remove () used with return
 a6bee4a hwmon: (amc6821) fix initialisation
 2faaa93 hwmon: (lm80) add error handling
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.10 (GNU/Linux)
 
 iQIcBAABAgAGBQJPaJBFAAoJEMsfJm/On5mBhkMP/09vlmsG7J3TLHcSKYJBkvSx
 6VNOOJgPqnvF71Az0dX47SU3zVXhG3I7dZufd/hqOK+0CNylSB7OSZMcWvBTduea
 0hDLTYj++SyVDQfVXb3zCVLU/wAE3YuXB3umWPwAKit4s2wAYYRDVCjwK96B88rv
 llNvo6JryuJDBUq7xiEmr0vKWMO0mKwwjpMTGCD3NpzK02ZV49T0gM94xa4gi5nM
 QAhNeO1AzQTx0+mBSRlq+SBBLSiXQmHcNrhnxcRMPha1bEi1D+QESozsczr+9/lz
 8vuTIULOIZxafM4XkBsZdknvlZnYrA6ukituDfVfiYQVcljO/cNu+seutFQDCMJe
 1zTDoNGIAwwnw0sAWWmTQwUMi+GSvlaL20gmm8FhTlvQaj9hNETsPYxEvPEsBNY1
 ICCixZcwpa1mZBXmryz2btf8az0OlX/sApzyHiq24B7lSE5Fv4tBDtwypLRu5N8m
 C4oNXC2dqDU0gtVxzO5Lavu6LHWV9lhyZvRPO75+zxYt4i5cnO04GTAYWh46aOzO
 DAZcs8M2Rj++dI5VW9Vl0k8hP9eWjxtPJFhNv/OWTx4YYQRICrde+j7QZcikIUWF
 0bzYI/zeIcwOg059vhnglBFM3mr7Z92jm4mftcNaSj/zuUHbWf6AQLbIq86Zq7tF
 3Eru3WuTZTwAkyNAVWd5
 =cUoW
 -----END PGP SIGNATURE-----

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

Pull hwmon changes for v3.4 from Guenter Roeck:
 "Mostly cleanup.  No new drivers this time around, but support for
  several chips added to existing drivers: TPS40400, TPS40422, MTD040,
  MAX34446, ZL9101M, ZL9117M, and LM96080.  Also, added watchdog support
  for SCH56xx, and additional attributes for a couple of drivers."

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (137 commits)
  hwmon: (sch56xx) Add support for the integrated watchdog (v2)
  hwmon: (w83627ehf) Add support for temperature offset registers
  hwmon: (jc42) Remove unnecessary device IDs
  hwmon: (zl6100) Add support for ZL9101M and ZL9117M
  hwmon: (adm1275) Add support for ADM1075
  hwmon: (max34440) Add support for MAX34446
  hwmon: (pmbus) Add more virtual registers
  hwmon: (pmbus) Add support for Lineage Power MDT040
  hwmon: (pmbus) Add support for TI TPS40400 and TPS40422
  hwmon: (max34440) Add support for 'lowest' output voltage attribute
  hwmon: (jc42) Convert to use devm_kzalloc
  hwmon: (max16065) Convert to use devm_kzalloc
  hwmon: (smm665) Convert to use devm_kzalloc
  hwmon: (ltc4261) Convert to use devm_kzalloc
  hwmon: (pmbus) Simplify remove functions
  hwmon: (pmbus) Convert pmbus drivers to use devm_kzalloc
  hwmon: (lineage-pem) Convert to use devm_kzalloc
  hwmon: (hwmon-vid) Fix checkpatch issues
  hwmon: (hwmon-vid) Add new entries to VRM model table
  hwmon: (lm80) Add detection of NatSemi/TI LM96080
  ...
This commit is contained in:
Linus Torvalds 2012-03-21 10:37:25 -07:00
commit 31f6765266
129 changed files with 8814 additions and 6452 deletions

View File

@ -2,6 +2,10 @@ Kernel driver adm1275
=====================
Supported chips:
* Analog Devices ADM1075
Prefix: 'adm1075'
Addresses scanned: -
Datasheet: www.analog.com/static/imported-files/data_sheets/ADM1075.pdf
* Analog Devices ADM1275
Prefix: 'adm1275'
Addresses scanned: -
@ -17,13 +21,13 @@ Author: Guenter Roeck <guenter.roeck@ericsson.com>
Description
-----------
This driver supports hardware montoring for Analog Devices ADM1275 and ADM1276
Hot-Swap Controller and Digital Power Monitor.
This driver supports hardware montoring for Analog Devices ADM1075, ADM1275,
and ADM1276 Hot-Swap Controller and Digital Power Monitor.
ADM1275 and ADM1276 are hot-swap controllers that allow a circuit board to be
removed from or inserted into a live backplane. They also feature current and
voltage readback via an integrated 12-bit analog-to-digital converter (ADC),
accessed using a PMBus interface.
ADM1075, ADM1275, and ADM1276 are hot-swap controllers that allow a circuit
board to be removed from or inserted into a live backplane. They also feature
current and voltage readback via an integrated 12-bit analog-to-digital
converter (ADC), accessed using a PMBus interface.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
@ -36,6 +40,10 @@ This driver does not auto-detect devices. You will have to instantiate the
devices explicitly. Please see Documentation/i2c/instantiating-devices for
details.
The ADM1075, unlike many other PMBus devices, does not support internal voltage
or current scaling. Reported voltages, currents, and power are raw measurements,
and will typically have to be scaled.
Platform data support
---------------------
@ -51,7 +59,8 @@ The following attributes are supported. Limits are read-write, history reset
attributes are write-only, all other attributes are read-only.
in1_label "vin1" or "vout1" depending on chip variant and
configuration.
configuration. On ADM1075, vout1 reports the voltage on
the VAUX pin.
in1_input Measured voltage.
in1_min Minimum Voltage.
in1_max Maximum voltage.
@ -74,3 +83,10 @@ curr1_crit Critical maximum current. Depending on the chip
curr1_crit_alarm Critical current high alarm.
curr1_highest Historical maximum current.
curr1_reset_history Write any value to reset history.
power1_label "pin1"
power1_input Input power.
power1_reset_history Write any value to reset history.
Power attributes are supported on ADM1075 and ADM1276
only.

View File

@ -3,71 +3,50 @@ Kernel driver jc42
Supported chips:
* Analog Devices ADT7408
Prefix: 'adt7408'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://www.analog.com/static/imported-files/data_sheets/ADT7408.pdf
* Atmel AT30TS00
Prefix: 'at30ts00'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://www.atmel.com/Images/doc8585.pdf
* IDT TSE2002B3, TSE2002GB2, TS3000B3, TS3000GB2
Prefix: 'tse2002', 'ts3000'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
http://www.idt.com/sites/default/files/documents/IDT_TSE2002GB2A1_DST_20111107_120303145914.pdf
http://www.idt.com/sites/default/files/documents/IDT_TS3000B3A_DST_20101129_120303152013.pdf
http://www.idt.com/sites/default/files/documents/IDT_TS3000GB2A1_DST_20111104_120303151012.pdf
* Maxim MAX6604
Prefix: 'max6604'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://datasheets.maxim-ic.com/en/ds/MAX6604.pdf
* Microchip MCP9804, MCP9805, MCP98242, MCP98243, MCP9843
Prefixes: 'mcp9804', 'mcp9805', 'mcp98242', 'mcp98243', 'mcp9843'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://ww1.microchip.com/downloads/en/DeviceDoc/22203C.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/21977b.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/21996a.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/22153c.pdf
* NXP Semiconductors SE97, SE97B
Prefix: 'se97'
Addresses scanned: I2C 0x18 - 0x1f
* NXP Semiconductors SE97, SE97B, SE98, SE98A
Datasheets:
http://www.nxp.com/documents/data_sheet/SE97.pdf
http://www.nxp.com/documents/data_sheet/SE97B.pdf
* NXP Semiconductors SE98
Prefix: 'se98'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://www.nxp.com/documents/data_sheet/SE98.pdf
http://www.nxp.com/documents/data_sheet/SE98A.pdf
* ON Semiconductor CAT34TS02, CAT6095
Prefix: 'cat34ts02', 'cat6095'
Addresses scanned: I2C 0x18 - 0x1f
Datasheet:
http://www.onsemi.com/pub_link/Collateral/CAT34TS02-D.PDF
http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
* ST Microelectronics STTS424, STTS424E02
Prefix: 'stts424'
Addresses scanned: I2C 0x18 - 0x1f
Datasheets:
http://www.st.com/stonline/products/literature/ds/13447/stts424.pdf
http://www.st.com/stonline/products/literature/ds/13448/stts424e02.pdf
* ST Microelectronics STTS2002, STTS3000
Prefix: 'stts2002', 'stts3000'
Addresses scanned: I2C 0x18 - 0x1f
* ST Microelectronics STTS424, STTS424E02, STTS2002, STTS3000
Datasheets:
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00157556.pdf
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00157558.pdf
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00225278.pdf
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATA_BRIEF/CD00270920.pdf
* JEDEC JC 42.4 compliant temperature sensor chips
Prefix: 'jc42'
Addresses scanned: I2C 0x18 - 0x1f
Datasheet:
http://www.jedec.org/sites/default/files/docs/4_01_04R19.pdf
Common for all chips:
Prefix: 'jc42'
Addresses scanned: I2C 0x18 - 0x1f
Author:
Guenter Roeck <guenter.roeck@ericsson.com>

View File

@ -7,6 +7,11 @@ Supported chips:
Addresses scanned: I2C 0x28 - 0x2f
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
* National Semiconductor LM96080
Prefix: 'lm96080'
Addresses scanned: I2C 0x28 - 0x2f
Datasheet: Publicly available at the National Semiconductor website
http://www.national.com/
Authors:
Frodo Looijaard <frodol@dds.nl>,
@ -17,7 +22,9 @@ Description
This driver implements support for the National Semiconductor LM80.
It is described as a 'Serial Interface ACPI-Compatible Microprocessor
System Hardware Monitor'.
System Hardware Monitor'. The LM96080 is a more recent incarnation,
it is pin and register compatible, with a few additional features not
yet supported by the driver.
The LM80 implements one temperature sensor, two fan rotation speed sensors,
seven voltage sensors, alarms, and some miscellaneous stuff.

View File

@ -11,6 +11,11 @@ Supported chips:
Prefixes: 'max34441'
Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
* Maxim MAX34446
PMBus Power-Supply Data Logger
Prefixes: 'max34446'
Addresses scanned: -
Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34446.pdf
Author: Guenter Roeck <guenter.roeck@ericsson.com>
@ -19,8 +24,8 @@ Description
-----------
This driver supports hardware montoring for Maxim MAX34440 PMBus 6-Channel
Power-Supply Manager and MAX34441 PMBus 5-Channel Power-Supply Manager
and Intelligent Fan Controller.
Power-Supply Manager, MAX34441 PMBus 5-Channel Power-Supply Manager
and Intelligent Fan Controller, and MAX34446 PMBus Power-Supply Data Logger.
The driver is a client driver to the core PMBus driver. Please see
Documentation/hwmon/pmbus for details on PMBus client drivers.
@ -33,6 +38,13 @@ This driver does not auto-detect devices. You will have to instantiate the
devices explicitly. Please see Documentation/i2c/instantiating-devices for
details.
For MAX34446, the value of the currX_crit attribute determines if current or
voltage measurement is enabled for a given channel. Voltage measurement is
enabled if currX_crit is set to 0; current measurement is enabled if the
attribute is set to a positive value. Power measurement is only enabled if
channel 1 (3) is configured for voltage measurement, and channel 2 (4) is
configured for current measurement.
Platform data support
---------------------
@ -56,19 +68,31 @@ in[1-6]_min_alarm Voltage low alarm. From VOLTAGE_UV_WARNING status.
in[1-6]_max_alarm Voltage high alarm. From VOLTAGE_OV_WARNING status.
in[1-6]_lcrit_alarm Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
in[1-6]_crit_alarm Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
in[1-6]_lowest Historical minimum voltage.
in[1-6]_highest Historical maximum voltage.
in[1-6]_reset_history Write any value to reset history.
MAX34446 only supports in[1-4].
curr[1-6]_label "iout[1-6]".
curr[1-6]_input Measured current. From READ_IOUT register.
curr[1-6]_max Maximum current. From IOUT_OC_WARN_LIMIT register.
curr[1-6]_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
curr[1-6]_max_alarm Current high alarm. From IOUT_OC_WARNING status.
curr[1-6]_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status.
curr[1-4]_average Historical average current (MAX34446 only).
curr[1-6]_highest Historical maximum current.
curr[1-6]_reset_history Write any value to reset history.
in6 and curr6 attributes only exist for MAX34440.
MAX34446 only supports curr[1-4].
power[1,3]_label "pout[1,3]"
power[1,3]_input Measured power.
power[1,3]_average Historical average power.
power[1,3]_highest Historical maximum power.
Power attributes only exist for MAX34446.
temp[1-8]_input Measured temperatures. From READ_TEMPERATURE_1 register.
temp1 is the chip's internal temperature. temp2..temp5
@ -79,7 +103,9 @@ temp[1-8]_max Maximum temperature. From OT_WARN_LIMIT register.
temp[1-8]_crit Critical high temperature. From OT_FAULT_LIMIT register.
temp[1-8]_max_alarm Temperature high alarm.
temp[1-8]_crit_alarm Temperature critical high alarm.
temp[1-8]_average Historical average temperature (MAX34446 only).
temp[1-8]_highest Historical maximum temperature.
temp[1-8]_reset_history Write any value to reset history.
temp7 and temp8 attributes only exist for MAX34440.
MAX34446 only supports temp[1-3].

View File

@ -15,13 +15,20 @@ Supported chips:
http://www.onsemi.com/pub_link/Collateral/NCP4200-D.PDF
http://www.onsemi.com/pub_link/Collateral/JUNE%202009-%20REV.%200.PDF
* Lineage Power
Prefixes: 'pdt003', 'pdt006', 'pdt012', 'udt020'
Prefixes: 'mdt040', 'pdt003', 'pdt006', 'pdt012', 'udt020'
Addresses scanned: -
Datasheets:
http://www.lineagepower.com/oem/pdf/PDT003A0X.pdf
http://www.lineagepower.com/oem/pdf/PDT006A0X.pdf
http://www.lineagepower.com/oem/pdf/PDT012A0X.pdf
http://www.lineagepower.com/oem/pdf/UDT020A0X.pdf
http://www.lineagepower.com/oem/pdf/MDT040A0X.pdf
* Texas Instruments TPS40400, TPS40422
Prefixes: 'tps40400', 'tps40422'
Addresses scanned: -
Datasheets:
http://www.ti.com/lit/gpn/tps40400
http://www.ti.com/lit/gpn/tps40422
* Generic PMBus devices
Prefix: 'pmbus'
Addresses scanned: -

View File

@ -16,6 +16,11 @@ Description
SMSC SCH5627 Super I/O chips include complete hardware monitoring
capabilities. They can monitor up to 5 voltages, 4 fans and 8 temperatures.
The SMSC SCH5627 hardware monitoring part also contains an integrated
watchdog. In order for this watchdog to function some motherboard specific
initialization most be done by the BIOS, so if the watchdog is not enabled
by the BIOS the sch5627 driver will not register a watchdog device.
The hardware monitoring part of the SMSC SCH5627 is accessed by talking
through an embedded microcontroller. An application note describing the
protocol for communicating with the microcontroller is available upon

View File

@ -26,6 +26,9 @@ temperatures. Note that the driver detects how many fan headers /
temperature sensors are actually implemented on the motherboard, so you will
likely see fewer temperature and fan inputs.
The Fujitsu Theseus hwmon solution also contains an integrated watchdog.
This watchdog is fully supported by the sch5636 driver.
An application note describing the Theseus' registers, as well as an
application note describing the protocol for communicating with the
microcontroller is available upon request. Please mail me if you want a copy.

View File

@ -34,6 +34,14 @@ Supported chips:
Prefix: 'zl6105'
Addresses scanned: -
Datasheet: http://www.intersil.com/data/fn/fn6906.pdf
* Intersil / Zilker Labs ZL9101M
Prefix: 'zl9101'
Addresses scanned: -
Datasheet: http://www.intersil.com/data/fn/fn7669.pdf
* Intersil / Zilker Labs ZL9117M
Prefix: 'zl9117'
Addresses scanned: -
Datasheet: http://www.intersil.com/data/fn/fn7914.pdf
* Ericsson BMR450, BMR451
Prefix: 'bmr450', 'bmr451'
Addresses scanned: -

View File

@ -598,11 +598,11 @@ config SENSORS_LM78
will be called lm78.
config SENSORS_LM80
tristate "National Semiconductor LM80"
tristate "National Semiconductor LM80 and LM96080"
depends on I2C
help
If you say yes here you get support for National Semiconductor
LM80 sensor chips.
LM80 and LM96080 sensor chips.
This driver can also be built as a module. If so, the module
will be called lm80.
@ -1028,7 +1028,8 @@ config SENSORS_SCH5627
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.
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.
@ -1044,7 +1045,8 @@ config SENSORS_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.
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.

View File

@ -1,25 +1,25 @@
/*
abituguru.c Copyright (c) 2005-2006 Hans de Goede <hdegoede@redhat.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; 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.
*/
* abituguru.c Copyright (c) 2005-2006 Hans de Goede <hdegoede@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; 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!
*/
* 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
@ -44,8 +44,10 @@
#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! */
/*
* 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 */
@ -70,16 +72,22 @@
#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. */
/*
* 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. */
/*
* 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. */
/*
* 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
@ -92,17 +100,25 @@
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 */
/*
* 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 */
/*
* 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 */
/*
* 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 */
/*
* 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 ( \
@ -110,10 +126,12 @@
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. */
/*
* 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 */
@ -130,16 +148,22 @@
/* 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 */
/*
* 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. */
/*
* 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! */
/*
* 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 };
@ -175,23 +199,29 @@ MODULE_PARM_DESC(verbose, "How verbose should the driver be? (0-3):\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. */
/*
* 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 */
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. */
/*
* 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];
@ -203,11 +233,15 @@ struct abituguru_data {
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). */
/*
* 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. */
/*
* 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 */
@ -236,8 +270,10 @@ static int abituguru_wait(struct abituguru_data *data, u8 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. */
/*
* 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);
}
@ -273,8 +309,10 @@ static int abituguru_ready(struct abituguru_data *data)
msleep(0);
}
/* After this the ABIT_UGURU_DATA port should contain
ABIT_UGURU_STATUS_INPUT */
/*
* 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--;
@ -290,27 +328,35 @@ static int abituguru_ready(struct abituguru_data *data)
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. */
/*
* 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. */
/*
* 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". */
/*
* 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 */
/*
* 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 "
@ -332,8 +378,10 @@ static int abituguru_send_address(struct abituguru_data *data,
}
}
/* 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. */
/*
* 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)
{
@ -362,13 +410,17 @@ static int abituguru_read(struct abituguru_data *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. */
/*
* 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 */
/*
* 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 */
@ -388,9 +440,11 @@ static int abituguru_write(struct abituguru_data *data,
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. */
/*
* 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,
@ -416,12 +470,14 @@ static int abituguru_write(struct abituguru_data *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. */
/*
* 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)
@ -448,16 +504,20 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
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. */
/*
* 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. */
/*
* 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;
@ -473,8 +533,10 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
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 */
/*
* 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. */
@ -497,17 +559,21 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
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. */
/*
* 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 */
/*
* 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. */
@ -532,9 +598,11 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
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. */
/*
* 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],
@ -548,23 +616,25 @@ abituguru_detect_bank1_sensor_type_exit:
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. */
/*
* 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)
{
@ -580,12 +650,14 @@ abituguru_detect_no_bank2_sensors(struct abituguru_data *data)
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?? */
/*
* 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",
@ -633,9 +705,11 @@ abituguru_detect_no_pwms(struct abituguru_data *data)
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 */
/*
* 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",
@ -643,8 +717,10 @@ abituguru_detect_no_pwms(struct abituguru_data *data)
break;
}
/* the low nibble must correspond to one of the temp sensors
we've found */
/*
* 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] ==
@ -711,9 +787,11 @@ abituguru_detect_no_pwms_exit:
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. */
/*
* 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,
@ -763,10 +841,18 @@ static ssize_t store_bank1_setting(struct device *dev, struct device_attribute
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
u8 val = (simple_strtoul(buf, NULL, 10) * 255 +
data->bank1_max_value[attr->index]/2) /
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];
ssize_t ret = count;
if (val > 255)
return -EINVAL;
mutex_lock(&data->update_lock);
if (data->bank1_settings[attr->index][attr->nr] != val) {
@ -788,13 +874,19 @@ static ssize_t store_bank2_setting(struct device *dev, struct device_attribute
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
u8 val = (simple_strtoul(buf, NULL, 10)*255 + ABIT_UGURU_FAN_MAX/2) /
ABIT_UGURU_FAN_MAX;
ssize_t ret = count;
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))
if (val < abituguru_bank2_min_threshold ||
val > abituguru_bank2_max_threshold)
return -EINVAL;
mutex_lock(&data->update_lock);
@ -819,11 +911,13 @@ static ssize_t show_bank1_alarm(struct device *dev,
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. */
/*
* 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");
@ -871,10 +965,15 @@ static ssize_t store_bank1_mask(struct device *dev,
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
int mask = simple_strtoul(buf, NULL, 10);
ssize_t ret = count;
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];
@ -899,10 +998,15 @@ static ssize_t store_bank2_mask(struct device *dev,
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
int mask = simple_strtoul(buf, NULL, 10);
ssize_t ret = count;
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];
@ -937,10 +1041,17 @@ static ssize_t store_pwm_setting(struct device *dev, struct device_attribute
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
u8 min, val = (simple_strtoul(buf, NULL, 10) +
abituguru_pwm_settings_multiplier[attr->nr]/2) /
abituguru_pwm_settings_multiplier[attr->nr];
ssize_t ret = count;
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)))
@ -949,7 +1060,7 @@ static ssize_t store_pwm_setting(struct device *dev, struct device_attribute
min = abituguru_pwm_min[attr->nr];
/* this check can be done before taking the lock */
if ((val < min) || (val > abituguru_pwm_max[attr->nr]))
if (val < min || val > abituguru_pwm_max[attr->nr])
return -EINVAL;
mutex_lock(&data->update_lock);
@ -981,8 +1092,10 @@ static ssize_t show_pwm_sensor(struct device *dev,
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. */
/*
* 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))
@ -996,27 +1109,32 @@ static ssize_t store_pwm_sensor(struct device *dev, struct device_attribute
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
unsigned long val = simple_strtoul(buf, NULL, 10) - 1;
ssize_t ret = count;
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);
if (val < data->bank1_sensors[ABIT_UGURU_TEMP_SENSOR]) {
u8 orig_val = data->pwm_settings[attr->index][0];
u8 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;
}
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;
}
}
else
ret = -EINVAL;
mutex_unlock(&data->update_lock);
return ret;
}
@ -1037,22 +1155,27 @@ static ssize_t store_pwm_enable(struct device *dev, struct device_attribute
{
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
struct abituguru_data *data = dev_get_drvdata(dev);
u8 orig_val, user_val = simple_strtoul(buf, NULL, 10);
ssize_t ret = count;
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;
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,
@ -1147,13 +1270,16 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
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. */
/*
* 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 };
if (!(data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL)))
data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
@ -1164,9 +1290,11 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
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. */
/*
* 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;
@ -1181,11 +1309,13 @@ static int __devinit abituguru_probe(struct platform_device *pdev)
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! */
/*
* 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,
@ -1332,24 +1462,26 @@ static struct abituguru_data *abituguru_update_device(struct device *dev)
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ)) {
success = 0;
if ((err = abituguru_read(data, ABIT_UGURU_ALARM_BANK, 0,
data->alarms, 3, 0)) != 3)
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++) {
if ((err = abituguru_read(data,
ABIT_UGURU_SENSOR_BANK1, i,
&data->bank1_value[i], 1, 0)) != 1)
err = abituguru_read(data, ABIT_UGURU_SENSOR_BANK1,
i, &data->bank1_value[i], 1, 0);
if (err != 1)
goto LEAVE_UPDATE;
if ((err = abituguru_read(data,
ABIT_UGURU_SENSOR_BANK1 + 1, i,
data->bank1_settings[i], 3, 0)) != 3)
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++)
if ((err = abituguru_read(data,
ABIT_UGURU_SENSOR_BANK2, i,
&data->bank2_value[i], 1, 0)) != 1)
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;
@ -1385,8 +1517,10 @@ LEAVE_UPDATE:
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 */
/*
* make sure all communications with the uguru are done and no new
* ones are started
*/
mutex_lock(&data->update_lock);
return 0;
}
@ -1418,12 +1552,14 @@ static struct platform_driver abituguru_driver = {
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! */
/*
* 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)) &&

View File

@ -1,28 +1,28 @@
/*
abituguru3.c
Copyright (c) 2006-2008 Hans de Goede <hdegoede@redhat.com>
Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
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.
*/
* abituguru3.c
*
* Copyright (c) 2006-2008 Hans de Goede <hdegoede@redhat.com>
* Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
*
* 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.
*/
* 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
@ -62,13 +62,17 @@
#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. */
/*
* 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 */
/*
* 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"
@ -78,32 +82,45 @@
/* 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 */
/*
* 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 */
/*
* 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). */
/*
* 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. */
/*
* 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. */
/*
* 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
@ -112,7 +129,7 @@
/* Structures */
struct abituguru3_sensor_info {
const char* name;
const char *name;
int port;
int type;
int multiplier;
@ -130,9 +147,11 @@ struct abituguru3_motherboard_info {
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. */
/*
* 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 */
@ -140,8 +159,10 @@ struct abituguru3_data {
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) */
/*
* 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];
@ -151,9 +172,11 @@ struct abituguru3_data {
/* 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 */
/*
* 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];
@ -161,9 +184,11 @@ struct abituguru3_data {
/* 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 */
/*
* 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];
};
@ -626,8 +651,10 @@ static int abituguru3_wait_while_busy(struct abituguru3_data *data)
timeout--;
if (timeout == 0)
return x;
/* sleep a bit before our last try, to give the uGuru3 one
last chance to respond. */
/*
* sleep a bit before our last try, to give the uGuru3 one
* last chance to respond.
*/
if (timeout == 1)
msleep(1);
}
@ -645,48 +672,57 @@ static int abituguru3_wait_for_read(struct abituguru3_data *data)
timeout--;
if (timeout == 0)
return x;
/* sleep a bit before our last try, to give the uGuru3 one
last chance to respond. */
/*
* 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. */
/*
* 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;
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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;
}
if ((x = abituguru3_wait_for_read(data)) != ABIT_UGURU3_SUCCESS) {
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;
@ -705,18 +741,22 @@ static int abituguru3_synchronize(struct abituguru3_data *data)
return 0;
}
/* Read count bytes from sensor sensor_addr in bank bank_addr and store the
result in buf */
/*
* 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;
if ((x = abituguru3_synchronize(data)))
x = abituguru3_synchronize(data);
if (x)
return x;
outb(0x1A, data->addr + ABIT_UGURU3_DATA);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
@ -724,7 +764,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
}
outb(bank, data->addr + ABIT_UGURU3_CMD);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
@ -732,7 +773,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
}
outb(offset, data->addr + ABIT_UGURU3_CMD);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
@ -740,7 +782,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
}
outb(count, data->addr + ABIT_UGURU3_CMD);
if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
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);
@ -748,8 +791,8 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
}
for (i = 0; i < count; i++) {
if ((x = abituguru3_wait_for_read(data)) !=
ABIT_UGURU3_SUCCESS) {
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);
@ -760,28 +803,34 @@ static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
return i;
}
/* Sensor settings are stored 1 byte per offset with the bytes
placed add consecutive offsets. */
/*
* 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++)
if ((x = abituguru3_read(data, bank, offset + i, count,
buf + i * count)) != count) {
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. */
/*
* 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,
@ -807,8 +856,10 @@ static ssize_t show_value(struct device *dev,
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 */
/*
* 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;
@ -827,10 +878,12 @@ static ssize_t show_alarm(struct device *dev,
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. */
/*
* 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");
@ -923,7 +976,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
u8 buf[2];
u16 id;
if (!(data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL)))
data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
@ -931,10 +985,10 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, data);
/* Read the motherboard ID */
if ((i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK,
ABIT_UGURU3_BOARD_ID, 2, buf)) != 2) {
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))
@ -1091,8 +1145,10 @@ LEAVE_UPDATE:
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 */
/*
* make sure all communications with the uguru3 are done and no new
* ones are started
*/
mutex_lock(&data->update_lock);
return 0;
}
@ -1134,7 +1190,8 @@ static int __init abituguru3_dmi_detect(void)
if (!board_name)
return err;
/* At the moment, we don't care about the part of the vendor
/*
* 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.
@ -1157,15 +1214,18 @@ static int __init abituguru3_dmi_detect(void)
return 1;
}
/* FIXME: Manual detection should die eventually; we need to collect stable
/*
* 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. */
/*
* 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)) &&
@ -1197,7 +1257,8 @@ static int __init abituguru3_init(void)
if (err < 0)
return err;
/* Fall back to manual detection if there was no exact
/*
* Fall back to manual detection if there was no exact
* board name match, or force was specified.
*/
if (err > 0) {

View File

@ -167,17 +167,7 @@ static struct spi_driver ad7314_driver = {
.id_table = ad7314_id,
};
static __init int ad7314_init(void)
{
return spi_register_driver(&ad7314_driver);
}
module_init(ad7314_init);
static __exit void ad7314_exit(void)
{
spi_unregister_driver(&ad7314_driver);
}
module_exit(ad7314_exit);
module_spi_driver(ad7314_driver);
MODULE_AUTHOR("Sonic Zhang <sonic.zhang@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7314, ADT7301 and ADT7302 digital"

View File

@ -50,7 +50,8 @@ struct ad7414_data {
/* 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
/*
* use integer division instead of equivalent right shift to
* guarantee arithmetic shift and preserve the sign
*/
return ((int)reg / 64) * 250;
@ -130,7 +131,11 @@ static ssize_t set_max_min(struct device *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 = simple_strtol(buf, NULL, 10);
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;
@ -252,17 +257,7 @@ static struct i2c_driver ad7414_driver = {
.id_table = ad7414_id,
};
static int __init ad7414_init(void)
{
return i2c_add_driver(&ad7414_driver);
}
module_init(ad7414_init);
static void __exit ad7414_exit(void)
{
i2c_del_driver(&ad7414_driver);
}
module_exit(ad7414_exit);
module_i2c_driver(ad7414_driver);
MODULE_AUTHOR("Stefan Roese <sr at denx.de>, "
"Frank Edelhaeuser <frank.edelhaeuser at spansion.com>");

View File

@ -167,7 +167,11 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -228,7 +232,8 @@ static int ad7418_probe(struct i2c_client *client,
goto exit;
}
if (!(data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL))) {
data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
@ -261,7 +266,8 @@ static int ad7418_probe(struct i2c_client *client,
ad7418_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
err = sysfs_create_group(&client->dev.kobj, &data->attrs);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
@ -289,20 +295,9 @@ static int ad7418_remove(struct i2c_client *client)
return 0;
}
static int __init ad7418_init(void)
{
return i2c_add_driver(&ad7418_driver);
}
static void __exit ad7418_exit(void)
{
i2c_del_driver(&ad7418_driver);
}
module_i2c_driver(ad7418_driver);
MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
MODULE_DESCRIPTION("AD7416/17/18 driver");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_VERSION);
module_init(ad7418_init);
module_exit(ad7418_exit);

View File

@ -248,18 +248,7 @@ static struct spi_driver adcxx_driver = {
.remove = __devexit_p(adcxx_remove),
};
static int __init init_adcxx(void)
{
return spi_register_driver(&adcxx_driver);
}
static void __exit exit_adcxx(void)
{
spi_unregister_driver(&adcxx_driver);
}
module_init(init_adcxx);
module_exit(exit_adcxx);
module_spi_driver(adcxx_driver);
MODULE_AUTHOR("Marc Pignat");
MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver");

View File

@ -1,23 +1,23 @@
/*
adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
Philip Edelbrock <phil@netroedge.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; 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.
*/
* adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl> and
* Philip Edelbrock <phil@netroedge.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
@ -70,10 +70,12 @@ enum chips {
/* 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 */
/*
* 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 {
@ -182,7 +184,13 @@ static ssize_t set_temp_max(struct device *dev,
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 = simple_strtol(buf, NULL, 10) / 1000;
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);
@ -201,7 +209,13 @@ static ssize_t set_temp_min(struct device *dev,
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 = simple_strtol(buf, NULL, 10) / 1000;
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);
@ -226,7 +240,14 @@ static ssize_t set_low_power(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1021_data *data = i2c_get_clientdata(client);
int low_power = simple_strtol(buf, NULL, 10) != 0;
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) {
@ -361,7 +382,8 @@ static int adm1021_probe(struct i2c_client *client,
adm1021_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1021_group)))
err = sysfs_create_group(&client->dev.kobj, &adm1021_group);
if (err)
goto error1;
data->hwmon_dev = hwmon_device_register(&client->dev);
@ -427,8 +449,10 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
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. */
/*
* 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(
@ -451,23 +475,12 @@ static struct adm1021_data *adm1021_update_device(struct device *dev)
return data;
}
static int __init sensors_adm1021_init(void)
{
return i2c_add_driver(&adm1021_driver);
}
module_i2c_driver(adm1021_driver);
static void __exit sensors_adm1021_exit(void)
{
i2c_del_driver(&adm1021_driver);
}
MODULE_AUTHOR ("Frodo Looijaard <frodol@dds.nl> and "
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
"Philip Edelbrock <phil@netroedge.com>");
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");
module_init(sensors_adm1021_init)
module_exit(sensors_adm1021_exit)

View File

@ -12,7 +12,7 @@
* 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
* 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
@ -91,15 +91,16 @@ enum chips { adm1025, ne1619 };
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 : \
#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))
((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))
(((val) < 0 ? (val) - 500 : \
(val) + 500) / 1000))
/*
* Functions declaration
@ -218,7 +219,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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]);
@ -234,7 +240,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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]);
@ -264,7 +275,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -280,7 +296,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -343,7 +364,14 @@ 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);
data->vrm = simple_strtoul(buf, NULL, 10);
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);
@ -462,14 +490,15 @@ static int adm1025_probe(struct i2c_client *client,
adm1025_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1025_group)))
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)) {
if ((err = sysfs_create_group(&client->dev.kobj,
&adm1025_group_in4)))
err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4);
if (err)
goto exit_remove;
}
@ -506,7 +535,7 @@ static void adm1025_init_client(struct i2c_client *client)
* setting yet, we better set the high limits to the max so that
* no alarm triggers.
*/
for (i=0; i<6; i++) {
for (i = 0; i < 6; i++) {
reg = i2c_smbus_read_byte_data(client,
ADM1025_REG_IN_MAX(i));
if (reg == 0)
@ -514,7 +543,7 @@ static void adm1025_init_client(struct i2c_client *client)
ADM1025_REG_IN_MAX(i),
0xFF);
}
for (i=0; i<2; i++) {
for (i = 0; i < 2; i++) {
reg = i2c_smbus_read_byte_data(client,
ADM1025_REG_TEMP_HIGH(i));
if (reg == 0)
@ -555,7 +584,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
int i;
dev_dbg(&client->dev, "Updating data.\n");
for (i=0; i<6; i++) {
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,
@ -563,7 +592,7 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
data->in_max[i] = i2c_smbus_read_byte_data(client,
ADM1025_REG_IN_MAX(i));
}
for (i=0; i<2; 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,
@ -589,19 +618,8 @@ static struct adm1025_data *adm1025_update_device(struct device *dev)
return data;
}
static int __init sensors_adm1025_init(void)
{
return i2c_add_driver(&adm1025_driver);
}
static void __exit sensors_adm1025_exit(void)
{
i2c_del_driver(&adm1025_driver);
}
module_i2c_driver(adm1025_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("ADM1025 driver");
MODULE_LICENSE("GPL");
module_init(sensors_adm1025_init);
module_exit(sensors_adm1025_exit);

View File

@ -1,27 +1,27 @@
/*
adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (C) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
Chip details at:
<http://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
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.
*/
* adm1026.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (C) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
* Copyright (C) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
*
* Chip details at:
*
* <http://www.onsemi.com/PowerSolutions/product.do?id=ADM1026>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
@ -90,7 +90,8 @@ MODULE_PARM_DESC(gpio_fan, "List of GPIO pins (0-7) to program as fan tachs");
#define E2CFG_ROM 0x08
#define E2CFG_CLK_EXT 0x80
/* There are 10 general analog inputs and 7 dedicated inputs
/*
* There are 10 general analog inputs and 7 dedicated inputs
* They are:
* 0 - 9 = AIN0 - AIN9
* 10 = Vbat
@ -117,7 +118,8 @@ static u16 ADM1026_REG_IN_MAX[] = {
0x43, 0x44, 0x45, 0x46, 0x47
};
/* Temperatures are:
/*
* Temperatures are:
* 0 - Internal
* 1 - External 1
* 2 - External 2
@ -170,12 +172,14 @@ static u16 ADM1026_REG_TEMP_OFFSET[] = { 0x1e, 0x6e, 0x6f };
#define ADM1026_FAN_CONTROL_TEMP_RANGE 20
#define ADM1026_PWM_MAX 255
/* Conversions. Rounding and limit checking is only done on the TO_REG
/*
* 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
/*
* 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.
@ -197,23 +201,25 @@ static int adm1026_scaling[] = { /* .001 Volts */
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
/*
* 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))
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_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_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))
@ -222,14 +228,16 @@ static int adm1026_scaling[] = { /* .001 Volts */
#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
/*
* 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)
#define DAC_TO_REG(val) (SENSORS_LIMIT(((((val) * 255) + 500) / 2500), 0, 255))
#define DAC_FROM_REG(val) (((val) * 2500) / 255)
/* Chip sampling rates
/*
* 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.
@ -243,11 +251,13 @@ static int adm1026_scaling[] = { /* .001 Volts */
#define ADM1026_DATA_INTERVAL (1 * HZ)
#define ADM1026_CONFIG_INTERVAL (5 * 60 * HZ)
/* We allow for multiple chips in a single system.
/*
* 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. */
* allocated, when a new client structure is allocated.
*/
struct pwm_data {
u8 pwm;
@ -388,17 +398,16 @@ static void adm1026_init_client(struct i2c_client *client)
dev_dbg(&client->dev, "THERM pin enabled. "
"GPIO16 disabled.\n");
}
if (data->config3 & CFG3_VREF_250) {
if (data->config3 & CFG3_VREF_250)
dev_dbg(&client->dev, "Vref is 2.50 Volts.\n");
} else {
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) {
for (i = 0; i <= 15; ++i) {
if ((i & 0x03) == 0) {
value = adm1026_read_value(client,
ADM1026_REG_GPIO_CFG_0_3 + i/4);
ADM1026_REG_GPIO_CFG_0_3 + i / 4);
}
data->gpio_config[i] = value & 0x03;
value >>= 2;
@ -408,7 +417,8 @@ static void adm1026_init_client(struct i2c_client *client)
/* ... and then print it */
adm1026_print_gpio(client);
/* If the user asks us to reprogram the GPIO config, then
/*
* If the user asks us to reprogram the GPIO config, then
* do it now.
*/
if (gpio_input[0] != -1 || gpio_output[0] != -1
@ -417,7 +427,8 @@ static void adm1026_init_client(struct i2c_client *client)
adm1026_fixup_gpio(client);
}
/* WE INTENTIONALLY make no changes to the limits,
/*
* 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
@ -428,7 +439,7 @@ static void adm1026_init_client(struct i2c_client *client)
* 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;
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 */
@ -440,7 +451,7 @@ static void adm1026_init_client(struct i2c_client *client)
/* 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) {
for (i = 0; i <= 7; ++i) {
data->fan_div[i] = DIV_FROM_REG(value & 0x03);
value >>= 2;
}
@ -452,7 +463,7 @@ static void adm1026_print_gpio(struct i2c_client *client)
int i;
dev_dbg(&client->dev, "GPIO config is:\n");
for (i = 0;i <= 7;++i) {
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 ? "" : "!",
@ -462,7 +473,7 @@ static void adm1026_print_gpio(struct i2c_client *client)
dev_dbg(&client->dev, "\tFAN%d\n", i);
}
}
for (i = 8;i <= 15;++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",
@ -485,52 +496,46 @@ static void adm1026_fixup_gpio(struct i2c_client *client)
int value;
/* Make the changes requested. */
/* We may need to unlock/stop monitoring or soft-reset the
/*
* 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) {
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) {
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;
}
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) {
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;
}
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) {
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) {
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 */
@ -538,7 +543,7 @@ static void adm1026_fixup_gpio(struct i2c_client *client)
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) {
for (i = 15, value = 0; i >= 0; --i) {
value <<= 2;
value |= data->gpio_config[i] & 0x03;
if ((i & 0x03) == 0) {
@ -563,22 +568,25 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
mutex_lock(&data->update_lock);
if (!data->valid
|| time_after(jiffies, data->last_reading + ADM1026_DATA_INTERVAL)) {
|| 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) {
for (i = 0; i <= 16; ++i) {
data->in[i] =
adm1026_read_value(client, ADM1026_REG_IN[i]);
}
for (i = 0;i <= 7;++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 */
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]);
}
@ -614,7 +622,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
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) {
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,
@ -624,7 +632,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
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) {
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);
@ -632,7 +640,8 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
}
for (i = 0; i <= 2; ++i) {
/* NOTE: temp_xxx[] are s8 and we assume 2's
/*
* NOTE: temp_xxx[] are s8 and we assume 2's
* complement "conversion" in the assignment
*/
data->temp_min[i] = adm1026_read_value(client,
@ -681,7 +690,7 @@ static struct adm1026_data *adm1026_update_device(struct device *dev)
data->gpio_config[16] = (data->config3 >> 6) & 0x03;
value = 0;
for (i = 0;i <= 15;++i) {
for (i = 0; i <= 15; ++i) {
if ((i & 0x03) == 0) {
value = adm1026_read_value(client,
ADM1026_REG_GPIO_CFG_0_3 + i/4);
@ -721,7 +730,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -744,7 +758,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -779,23 +798,31 @@ in_reg(13);
in_reg(14);
in_reg(15);
static ssize_t show_in16(struct device *dev, struct device_attribute *attr, char *buf)
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)
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)
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);
int val = simple_strtol(buf, NULL, 10);
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);
@ -803,17 +830,24 @@ static ssize_t set_in16_min(struct device *dev, struct device_attribute *attr, c
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, char *buf)
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)
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);
int val = simple_strtol(buf, NULL, 10);
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);
@ -823,10 +857,10 @@ static ssize_t set_in16_max(struct device *dev, struct device_attribute *attr, c
}
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);
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 */
@ -856,7 +890,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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]);
@ -890,9 +929,8 @@ static void fixup_fan_min(struct device *dev, int fan, int old_div)
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) {
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);
@ -916,9 +954,14 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val, orig_div, new_div;
long val;
int orig_div, new_div;
int err;
err = kstrtol(buf, 10, &val);
if (err)
return err;
val = simple_strtol(buf, NULL, 10);
new_div = DIV_TO_REG(val);
mutex_lock(&data->update_lock);
@ -939,9 +982,9 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
(DIV_TO_REG(data->fan_div[7]) << 6));
}
if (data->fan_div[nr] != orig_div) {
if (data->fan_div[nr] != orig_div)
fixup_fan_min(dev, nr, orig_div);
}
mutex_unlock(&data->update_lock);
return count;
}
@ -983,7 +1026,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1007,7 +1055,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1046,7 +1099,12 @@ static ssize_t set_temp_offset(struct device *dev,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1056,8 +1114,8 @@ static ssize_t set_temp_offset(struct device *dev,
return count;
}
#define temp_offset_reg(offset) \
static SENSOR_DEVICE_ATTR(temp##offset##_offset, S_IRUGO | S_IWUSR, \
#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);
@ -1097,7 +1155,12 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1131,15 +1194,21 @@ static ssize_t set_temp_crit_enable(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
if ((val == 1) || (val==0)) {
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;
}
@ -1166,7 +1235,12 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr,
int nr = sensor_attr->index;
struct i2c_client *client = to_i2c_client(dev);
struct adm1026_data *data = i2c_get_clientdata(client);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1184,17 +1258,24 @@ 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)
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)
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);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1206,7 +1287,8 @@ static ssize_t set_analog_out_reg(struct device *dev, struct device_attribute *a
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)
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;
@ -1214,25 +1296,35 @@ static ssize_t show_vid_reg(struct device *dev, struct device_attribute *attr, c
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)
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)
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;
data->vrm = simple_strtol(buf, NULL, 10);
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)
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);
@ -1277,18 +1369,24 @@ 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)
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)
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);
int val = simple_strtol(buf, NULL, 10);
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;
@ -1313,18 +1411,24 @@ 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)
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)
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);
int val = simple_strtol(buf, NULL, 10);
long gpio;
long val;
int err;
err = kstrtol(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
data->gpio = val & 0x1ffff;
@ -1340,19 +1444,24 @@ static ssize_t set_gpio(struct device *dev, struct device_attribute *attr, const
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)
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)
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);
int val = simple_strtol(buf, NULL, 10);
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;
@ -1368,19 +1477,26 @@ static ssize_t set_gpio_mask(struct device *dev, struct device_attribute *attr,
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)
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)
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) {
int val = simple_strtol(buf, NULL, 10);
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);
@ -1389,17 +1505,26 @@ static ssize_t set_pwm_reg(struct device *dev, struct device_attribute *attr, co
}
return count;
}
static ssize_t show_auto_pwm_min(struct device *dev, struct device_attribute *attr, char *buf)
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)
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);
int val = simple_strtol(buf, NULL, 10);
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);
@ -1411,44 +1536,53 @@ static ssize_t set_auto_pwm_min(struct device *dev, struct device_attribute *att
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t show_auto_pwm_max(struct device *dev, struct device_attribute *attr, char *buf)
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)
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)
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 val = simple_strtol(buf, NULL, 10);
int old_enable;
unsigned long val;
int err;
if ((val >= 0) && (val < 3)) {
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);
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;
}
@ -1716,7 +1850,8 @@ static int adm1026_probe(struct i2c_client *client,
adm1026_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1026_group)))
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,
@ -1761,20 +1896,9 @@ static int adm1026_remove(struct i2c_client *client)
return 0;
}
static int __init sm_adm1026_init(void)
{
return i2c_add_driver(&adm1026_driver);
}
static void __exit sm_adm1026_exit(void)
{
i2c_del_driver(&adm1026_driver);
}
module_i2c_driver(adm1026_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
"Justin Thiessen <jthiessen@penguincomputing.com>");
MODULE_DESCRIPTION("ADM1026 driver");
module_init(sm_adm1026_init);
module_exit(sm_adm1026_exit);

View File

@ -78,7 +78,7 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
#define TEMP_FROM_REG(val) ((val) * 1000)
#define DIV_FROM_REG(val) ( 1 << (((val) >> 6) - 1))
#define DIV_FROM_REG(val) (1 << (((val) >> 6) - 1))
/* Registers to be checked by adm1029_update_device() */
static const u8 ADM1029_REG_TEMP[] = {
@ -200,8 +200,11 @@ static ssize_t set_fan_div(struct device *dev,
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);
long val = simple_strtol(buf, NULL, 10);
u8 reg;
long val;
int ret = kstrtol(buf, 10, &val);
if (ret < 0)
return ret;
mutex_lock(&data->update_lock);
@ -237,9 +240,9 @@ static ssize_t set_fan_div(struct device *dev,
}
/*
Access rights on sysfs, S_IRUGO stand for Is Readable by User, Group and Others
S_IWUSR stand for Is Writable by User
*/
* 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);
@ -300,7 +303,8 @@ static int adm1029_detect(struct i2c_client *client,
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
/* ADM1029 doesn't have CHIP ID, check just MAN ID
/*
* ADM1029 doesn't have CHIP ID, check just MAN ID
* For better detection we check also ADM1029_TEMP_DEVICES_INSTALLED,
* ADM1029_REG_NB_FAN_SUPPORT and compare it with possible values
* documented
@ -318,8 +322,10 @@ static int adm1029_detect(struct i2c_client *client,
return -ENODEV;
if ((chip_id & 0xF0) != 0x00) {
/* There are no "official" CHIP ID, so actually
* we use Major/Minor revision for that */
/*
* 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;
@ -355,7 +361,8 @@ static int adm1029_probe(struct i2c_client *client,
}
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &adm1029_group)))
err = sysfs_create_group(&client->dev.kobj, &adm1029_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
@ -403,8 +410,8 @@ static int adm1029_remove(struct i2c_client *client)
}
/*
function that update the status of the chips (temperature for example)
*/
* 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);
@ -446,24 +453,8 @@ static struct adm1029_data *adm1029_update_device(struct device *dev)
return data;
}
/*
Common module stuff
*/
static int __init sensors_adm1029_init(void)
{
return i2c_add_driver(&adm1029_driver);
}
static void __exit sensors_adm1029_exit(void)
{
i2c_del_driver(&adm1029_driver);
}
module_i2c_driver(adm1029_driver);
MODULE_AUTHOR("Corentin LABBE <corentin.labbe@geomatys.fr>");
MODULE_DESCRIPTION("adm1029 driver");
MODULE_LICENSE("GPL v2");
module_init(sensors_adm1029_init);
module_exit(sensors_adm1029_exit);

View File

@ -1,25 +1,25 @@
/*
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 <alex@alexdalton.org>
Reworked by Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* 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 <alex@alexdalton.org>
* Reworked by Jean Delvare <khali@linux-fr.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
@ -80,7 +80,8 @@ struct adm1031_data {
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
/*
* The chan_select_table contains the possible configurations for
* auto fan control.
*/
const auto_chan_table_t *chan_select_table;
@ -205,7 +206,8 @@ static int AUTO_TEMP_MAX_TO_REG(int val, int reg, int pwm)
#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
/*
* 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.
@ -226,7 +228,8 @@ static const auto_chan_table_t auto_channel_select_table_adm1030 = {
{ 3 /* 0b11 */ , 0 },
};
/* That function checks if a bitfield is valid and returns the other bitfield
/*
* That function checks if a bitfield is valid and returns the other bitfield
* nearest match if no exact match where found.
*/
static int
@ -252,7 +255,8 @@ get_fan_auto_nearest(struct adm1031_data *data,
break;
} else if (val == (*data->chan_select_table)[i][chan] &&
first_match == -1) {
/* Save the first match in case of an exact match has
/*
* Save the first match in case of an exact match has
* not been found
*/
first_match = i;
@ -306,9 +310,11 @@ set_fan_auto_channel(struct device *dev, struct device_attribute *attr,
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
/*
* Switch to Auto Fan Mode
* Save PWM registers
* Set PWM registers to 33% Both */
* 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);
@ -1131,19 +1137,8 @@ static struct adm1031_data *adm1031_update_device(struct device *dev)
return data;
}
static int __init sensors_adm1031_init(void)
{
return i2c_add_driver(&adm1031_driver);
}
static void __exit sensors_adm1031_exit(void)
{
i2c_del_driver(&adm1031_driver);
}
module_i2c_driver(adm1031_driver);
MODULE_AUTHOR("Alexandre d'Alton <alex@alexdalton.org>");
MODULE_DESCRIPTION("ADM1031/ADM1030 driver");
MODULE_LICENSE("GPL");
module_init(sensors_adm1031_init);
module_exit(sensors_adm1031_exit);

View File

@ -1,12 +1,12 @@
/*
* adm9240.c Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* monitoring
*
* Copyright (C) 1999 Frodo Looijaard <frodol@dds.nl>
* Philip Edelbrock <phil@netroedge.com>
* Copyright (C) 2003 Michiel Rook <michiel@grendelproject.nl>
* Copyright (C) 2005 Grant Coady <gcoady.lk@gmail.com> with valuable
* guidance from Jean Delvare
* guidance from Jean Delvare
*
* Driver supports Analog Devices ADM9240
* Dallas Semiconductor DS1780
@ -204,7 +204,12 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -255,7 +260,12 @@ static ssize_t set_in_min(struct device *dev,
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 = simple_strtoul(buf, NULL, 10);
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);
@ -272,7 +282,12 @@ static ssize_t set_in_max(struct device *dev,
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 = simple_strtoul(buf, NULL, 10);
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);
@ -283,7 +298,7 @@ static ssize_t set_in_max(struct device *dev,
}
#define vin(nr) \
static SENSOR_DEVICE_ATTR(in##nr##_input, S_IRUGO, \
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); \
@ -357,9 +372,14 @@ static ssize_t set_fan_min(struct device *dev,
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 = simple_strtoul(buf, NULL, 10);
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);
@ -465,7 +485,12 @@ static ssize_t set_aout(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct adm9240_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtol(buf, NULL, 10);
long val;
int err;
err = kstrtol(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
data->aout = AOUT_TO_REG(val);
@ -481,7 +506,12 @@ static ssize_t chassis_clear_legacy(struct device *dev,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
unsigned long val = simple_strtol(buf, NULL, 10);
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");
@ -632,7 +662,8 @@ static int adm9240_probe(struct i2c_client *new_client,
adm9240_init_client(new_client);
/* populate sysfs filesystem */
if ((err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group)))
err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
@ -681,8 +712,7 @@ static void adm9240_init_client(struct i2c_client *client)
} else { /* cold start: open limits before starting chip */
int i;
for (i = 0; i < 6; 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,
@ -717,8 +747,7 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4))
|| !data->valid) {
for (i = 0; i < 6; i++) /* read voltages */
{
for (i = 0; i < 6; i++) { /* read voltages */
data->in[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_IN(i));
}
@ -727,16 +756,17 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
i2c_smbus_read_byte_data(client,
ADM9240_REG_INT(1)) << 8;
/* read temperature: assume temperature changes less than
/*
* 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 */
* 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 */
{
for (i = 0; i < 2; i++) { /* read fans */
data->fan[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_FAN(i));
@ -760,15 +790,13 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
if (time_after(jiffies, data->last_updated_config + (HZ * 300))
|| !data->valid) {
for (i = 0; i < 6; i++)
{
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++)
{
for (i = 0; i < 2; i++) {
data->fan_min[i] = i2c_smbus_read_byte_data(client,
ADM9240_REG_FAN_MIN(i));
}
@ -795,21 +823,9 @@ static struct adm9240_data *adm9240_update_device(struct device *dev)
return data;
}
static int __init sensors_adm9240_init(void)
{
return i2c_add_driver(&adm9240_driver);
}
static void __exit sensors_adm9240_exit(void)
{
i2c_del_driver(&adm9240_driver);
}
module_i2c_driver(adm9240_driver);
MODULE_AUTHOR("Michiel Rook <michiel@grendelproject.nl>, "
"Grant Coady <gcoady.lk@gmail.com> and others");
MODULE_DESCRIPTION("ADM9240/DS1780/LM81 driver");
MODULE_LICENSE("GPL");
module_init(sensors_adm9240_init);
module_exit(sensors_adm9240_exit);

View File

@ -305,19 +305,8 @@ static struct i2c_driver ads1015_driver = {
.id_table = ads1015_id,
};
static int __init sensors_ads1015_init(void)
{
return i2c_add_driver(&ads1015_driver);
}
static void __exit sensors_ads1015_exit(void)
{
i2c_del_driver(&ads1015_driver);
}
module_i2c_driver(ads1015_driver);
MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>");
MODULE_DESCRIPTION("ADS1015 driver");
MODULE_LICENSE("GPL");
module_init(sensors_ads1015_init);
module_exit(sensors_ads1015_exit);

View File

@ -1,27 +1,27 @@
/*
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 <shardy@redhat.com>
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.
*/
* 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 <shardy@redhat.com>
*
* 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 <linux/module.h>
#include <linux/init.h>
@ -188,12 +188,13 @@ static int ads7828_detect(struct i2c_client *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)
*/
/*
* 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);

View File

@ -34,9 +34,11 @@
#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 */
/*
* 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)
@ -105,8 +107,10 @@ static ssize_t show_voltage(struct device *dev,
uint8_t channel, mux_cnv;
channel = attr->index;
/*TODO: add support for conversions
*other than single ended with a gain of 1*/
/*
* 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,
@ -114,8 +118,10 @@ static ssize_t show_voltage(struct device *dev,
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*/
/*
* 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);
@ -179,8 +185,10 @@ static int __devinit ads7871_probe(struct spi_device *spi)
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*/
/*
* 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;
@ -234,18 +242,7 @@ static struct spi_driver ads7871_driver = {
.remove = __devexit_p(ads7871_remove),
};
static int __init ads7871_init(void)
{
return spi_register_driver(&ads7871_driver);
}
static void __exit ads7871_exit(void)
{
spi_unregister_driver(&ads7871_driver);
}
module_init(ads7871_init);
module_exit(ads7871_exit);
module_spi_driver(ads7871_driver);
MODULE_AUTHOR("Paul Thomas <pthomas8589@gmail.com>");
MODULE_DESCRIPTION("TI ADS7871 A/D driver");

View File

@ -8,7 +8,7 @@
* published by the Free Software Foundation.
*
* TODO: SPI, support for external temperature sensor
* use power-down mode for suspend?, interrupt handling?
* use power-down mode for suspend?, interrupt handling?
*/
#include <linux/kernel.h>
@ -348,17 +348,7 @@ static struct i2c_driver adt7411_driver = {
.class = I2C_CLASS_HWMON,
};
static int __init sensors_adt7411_init(void)
{
return i2c_add_driver(&adt7411_driver);
}
module_init(sensors_adt7411_init)
static void __exit sensors_adt7411_exit(void)
{
i2c_del_driver(&adt7411_driver);
}
module_exit(sensors_adt7411_exit)
module_i2c_driver(adt7411_driver);
MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de> and "
"Wolfram Sang <w.sang@pengutronix.de>");

View File

@ -65,8 +65,8 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
#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_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
@ -85,7 +85,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
#define ADT7462_PIN15_INPUT 0x20
#define ADT7462_PIN13_INPUT 0x40
#define ADT7462_PIN8_INPUT 0x80
#define ADT7462_PIN23_MASK 0x03
#define ADT7462_PIN23_MASK 0x03
#define ADT7462_PIN23_SHIFT 0
#define ADT7462_PIN26_MASK 0x0C /* cfg2 */
#define ADT7462_PIN26_SHIFT 2
@ -99,7 +99,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
#define ADT7462_PIN28_VOLT 0x5
#define ADT7462_REG_ALARM1 0xB8
#define ADT7462_LT_ALARM 0x02
#define ADT7462_LT_ALARM 0x02
#define ADT7462_R1T_ALARM 0x04
#define ADT7462_R2T_ALARM 0x08
#define ADT7462_R3T_ALARM 0x10
@ -135,9 +135,9 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END };
#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 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
@ -1727,8 +1727,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
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[] =
{
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,
@ -1975,19 +1974,8 @@ static int adt7462_remove(struct i2c_client *client)
return 0;
}
static int __init adt7462_init(void)
{
return i2c_add_driver(&adt7462_driver);
}
static void __exit adt7462_exit(void)
{
i2c_del_driver(&adt7462_driver);
}
module_i2c_driver(adt7462_driver);
MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
MODULE_DESCRIPTION("ADT7462 driver");
MODULE_LICENSE("GPL");
module_init(adt7462_init);
module_exit(adt7462_exit);

View File

@ -1131,8 +1131,7 @@ static SENSOR_DEVICE_ATTR(pwm3_auto_channels_temp, S_IWUSR | S_IRUGO,
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[] =
{
static struct attribute *adt7470_attr[] = {
&dev_attr_alarm_mask.attr,
&dev_attr_num_temp_sensors.attr,
&dev_attr_auto_update_interval.attr,
@ -1276,7 +1275,8 @@ static int adt7470_probe(struct i2c_client *client,
/* Register sysfs hooks */
data->attrs.attrs = adt7470_attr;
if ((err = sysfs_create_group(&client->dev.kobj, &data->attrs)))
err = sysfs_create_group(&client->dev.kobj, &data->attrs);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
@ -1317,19 +1317,8 @@ static int adt7470_remove(struct i2c_client *client)
return 0;
}
static int __init adt7470_init(void)
{
return i2c_add_driver(&adt7470_driver);
}
static void __exit adt7470_exit(void)
{
i2c_del_driver(&adt7470_driver);
}
module_i2c_driver(adt7470_driver);
MODULE_AUTHOR("Darrick J. Wong <djwong@us.ibm.com>");
MODULE_DESCRIPTION("ADT7470 driver");
MODULE_LICENSE("GPL");
module_init(adt7470_init);
module_exit(adt7470_exit);

View File

@ -32,9 +32,10 @@
#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
*/
/*
* 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
@ -288,8 +289,10 @@ static void adt7475_write_word(struct i2c_client *client, int reg, u16 val)
i2c_smbus_write_byte_data(client, reg, val & 0xFF);
}
/* Find the nearest value in a table - used for pwm frequency and
auto temp range */
/*
* 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;
@ -385,16 +388,20 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
out = (out >> 4) & 0xF;
else
out = (out & 0xF);
/* Show the value as an absolute number tied to
* THERM */
/*
* 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 */
/*
* 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)
@ -452,8 +459,10 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
break;
case HYSTERSIS:
/* The value will be given as an absolute value, turn it
into an offset based on THERM */
/*
* 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] =
@ -478,8 +487,10 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
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 */
/*
* 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);
}
@ -514,8 +525,10 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
return count;
}
/* Table of autorange values - the user will write the value in millidegrees,
and we'll convert it */
/*
* 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,
@ -558,8 +571,10 @@ static ssize_t set_point2(struct device *dev, struct device_attribute *attr,
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 */
/*
* 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]);
@ -664,8 +679,10 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
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 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;
@ -1232,7 +1249,7 @@ static void adt7475_remove_files(struct i2c_client *client,
static int adt7475_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
static const char *names[] = {
static const char * const names[] = {
[adt7473] = "ADT7473",
[adt7475] = "ADT7475",
[adt7476] = "ADT7476",
@ -1280,9 +1297,11 @@ static int adt7475_probe(struct i2c_client *client,
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 */
/*
* 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))
@ -1294,8 +1313,10 @@ static int adt7475_probe(struct i2c_client *client,
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 */
/*
* 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))
@ -1314,8 +1335,10 @@ static int adt7475_probe(struct i2c_client *client,
}
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 */
/*
* 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);
@ -1431,8 +1454,10 @@ static void adt7475_read_pwm(struct i2c_client *client, int index)
data->pwm[CONTROL][index] = adt7475_read(PWM_CONFIG_REG(index));
/* Figure out the internal value for pwmctrl and pwmchan
based on the current settings */
/*
* Figure out the internal value for pwmctrl and pwmchan
* based on the current settings
*/
v = (data->pwm[CONTROL][index] >> 5) & 7;
if (v == 3)
@ -1440,10 +1465,11 @@ static void adt7475_read_pwm(struct i2c_client *client, int index)
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
*/
/*
* 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);
@ -1600,19 +1626,8 @@ static struct adt7475_data *adt7475_update_device(struct device *dev)
return data;
}
static int __init sensors_adt7475_init(void)
{
return i2c_add_driver(&adt7475_driver);
}
static void __exit sensors_adt7475_exit(void)
{
i2c_del_driver(&adt7475_driver);
}
module_i2c_driver(adt7475_driver);
MODULE_AUTHOR("Advanced Micro Devices, Inc");
MODULE_DESCRIPTION("adt7475 driver");
MODULE_LICENSE("GPL");
module_init(sensors_adt7475_init);
module_exit(sensors_adt7475_exit);

View File

@ -1,25 +1,25 @@
/*
amc6821.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si>
Based on max6650.c:
Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
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.
*/
* amc6821.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (C) 2009 T. Mertelj <tomaz.mertelj@guest.arnes.si>
*
* Based on max6650.c:
* Copyright (C) 2007 Hans J. Koch <hjk@hansjkoch.de>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/kernel.h> /* Needed for KERN_INFO */
@ -47,7 +47,7 @@ static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e,
* Insmod parameters
*/
static int pwminv = 0; /*Inverted PWM output. */
static int pwminv; /*Inverted PWM output. */
module_param(pwminv, int, S_IRUGO);
static int init = 1; /*Power-on initialization.*/
@ -188,7 +188,7 @@ static struct i2c_driver amc6821_driver = {
/*
* Client data (each client gets its own)
*/
*/
struct amc6821_data {
struct device *hwmon_dev;
@ -836,8 +836,10 @@ static int amc6821_detect(
return -ENODEV;
}
/* Bit 7 of the address register is ignored, so we can check the
ID registers again */
/*
* 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) {
@ -1080,9 +1082,10 @@ static struct amc6821_data *amc6821_update_device(struct device *dev)
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
*/
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;
@ -1095,20 +1098,7 @@ static struct amc6821_data *amc6821_update_device(struct device *dev)
return data;
}
static int __init amc6821_init(void)
{
return i2c_add_driver(&amc6821_driver);
}
static void __exit amc6821_exit(void)
{
i2c_del_driver(&amc6821_driver);
}
module_init(amc6821_init);
module_exit(amc6821_exit);
module_i2c_driver(amc6821_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("T. Mertelj <tomaz.mertelj@guest.arnes.si>");

View File

@ -344,8 +344,10 @@ static int applesmc_get_lower_bound(unsigned int *lo, const char *key)
while (begin != end) {
int middle = begin + (end - begin) / 2;
entry = applesmc_get_entry_by_index(middle);
if (IS_ERR(entry))
if (IS_ERR(entry)) {
*lo = 0;
return PTR_ERR(entry);
}
if (strcmp(entry->key, key) < 0)
begin = middle + 1;
else
@ -364,8 +366,10 @@ static int applesmc_get_upper_bound(unsigned int *hi, const char *key)
while (begin != end) {
int middle = begin + (end - begin) / 2;
entry = applesmc_get_entry_by_index(middle);
if (IS_ERR(entry))
if (IS_ERR(entry)) {
*hi = smcreg.key_count;
return PTR_ERR(entry);
}
if (strcmp(key, entry->key) < 0)
end = middle;
else
@ -1189,8 +1193,10 @@ 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". */
/*
* 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"),

View File

@ -1,40 +1,40 @@
/*
asb100.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (C) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
(derived from w83781d.c)
Copyright (C) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>, and
Mark Studebaker <mdsxyz123@yahoo.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; 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.
*/
* asb100.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
*
* Copyright (C) 2004 Mark M. Hoffman <mhoffman@lightlink.com>
*
* (derived from w83781d.c)
*
* Copyright (C) 1998 - 2003 Frodo Looijaard <frodol@dds.nl>,
* Philip Edelbrock <phil@netroedge.com>, and
* Mark Studebaker <mdsxyz123@yahoo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; 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
*/
* 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
@ -99,15 +99,19 @@ static const u16 asb100_reg_temp_hyst[] = {0, 0x3a, 0x153, 0x253, 0x19};
/* 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. */
/*
* 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)
#define ASB100_IN_MIN 0
#define ASB100_IN_MAX 4080
/* IN: 1/1000 V (0V to 4.08V)
REG: 16mV/bit */
/*
* 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);
@ -131,19 +135,21 @@ static u8 FAN_TO_REG(long rpm, int div)
static int FAN_FROM_REG(u8 val, int div)
{
return val==0 ? -1 : val==255 ? 0 : 1350000/(val*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)
#define ASB100_TEMP_MIN -128000
#define ASB100_TEMP_MAX 127000
/* TEMP: 0.001C/bit (-128C to +127C)
REG: 1C/bit, two's complement */
/*
* 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);
ntemp += (ntemp < 0 ? -500 : 500);
return (u8)(ntemp / 1000);
}
@ -152,8 +158,10 @@ static int TEMP_FROM_REG(u8 reg)
return (s8)reg * 1000;
}
/* PWM: 0 - 255 per sensors documentation
REG: (6.25% duty cycle per bit) */
/*
* 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);
@ -167,16 +175,20 @@ static int ASB100_PWM_FROM_REG(u8 reg)
#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) */
/*
* 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;
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. */
/*
* 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;
@ -253,8 +265,10 @@ static ssize_t set_in_##reg(struct device *dev, struct device_attribute *attr, \
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 = simple_strtoul(buf, NULL, 10); \
\
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), \
@ -315,7 +329,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
int nr = to_sensor_dev_attr(attr)->index;
struct i2c_client *client = to_i2c_client(dev);
struct asb100_data *data = i2c_get_clientdata(client);
u32 val = simple_strtoul(buf, NULL, 10);
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]));
@ -324,10 +343,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
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. */
/*
* 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)
{
@ -335,8 +356,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct asb100_data *data = i2c_get_clientdata(client);
unsigned long min;
unsigned long val = simple_strtoul(buf, NULL, 10);
int reg;
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
@ -421,8 +447,10 @@ static ssize_t set_##reg(struct device *dev, struct device_attribute *attr, \
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 = simple_strtol(buf, NULL, 10); \
\
long val; \
int err = kstrtol(buf, 10, &val); \
if (err) \
return err; \
mutex_lock(&data->update_lock); \
switch (nr) { \
case 1: case 2: \
@ -476,7 +504,13 @@ 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);
data->vrm = simple_strtoul(buf, NULL, 10);
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
data->vrm = val;
return count;
}
@ -524,7 +558,12 @@ static ssize_t set_pwm1(struct device *dev, struct device_attribute *attr,
{
struct i2c_client *client = to_i2c_client(dev);
struct asb100_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
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 */
@ -546,7 +585,12 @@ static ssize_t set_pwm_enable1(struct device *dev,
{
struct i2c_client *client = to_i2c_client(dev);
struct asb100_data *data = i2c_get_clientdata(client);
unsigned long val = simple_strtoul(buf, NULL, 10);
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 */
@ -768,7 +812,8 @@ static int asb100_probe(struct i2c_client *client,
data->fan_min[2] = asb100_read_value(client, ASB100_REG_FAN_MIN(2));
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &asb100_group)))
err = sysfs_create_group(&client->dev.kobj, &asb100_group);
if (err)
goto ERROR3;
data->hwmon_dev = hwmon_device_register(&client->dev);
@ -805,8 +850,10 @@ static int asb100_remove(struct i2c_client *client)
return 0;
}
/* The SMBus locks itself, usually, but nothing may access the chip between
bank switches. */
/*
* 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);
@ -971,19 +1018,8 @@ static struct asb100_data *asb100_update_device(struct device *dev)
return data;
}
static int __init asb100_init(void)
{
return i2c_add_driver(&asb100_driver);
}
static void __exit asb100_exit(void)
{
i2c_del_driver(&asb100_driver);
}
module_i2c_driver(asb100_driver);
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
MODULE_DESCRIPTION("ASB100 Bach driver");
MODULE_LICENSE("GPL");
module_init(asb100_init);
module_exit(asb100_exit);

View File

@ -268,9 +268,11 @@ static ssize_t store_fan16(struct device *dev,
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. */
/*
* 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));

View File

@ -38,7 +38,8 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = {
{ }
};
/* Minimum time between readings, enforced in order to avoid
/*
* Minimum time between readings, enforced in order to avoid
* hogging the CPU.
*/
#define CACHE_TIME HZ
@ -161,7 +162,8 @@ struct atk_sensor_data {
char const *acpi_name;
};
/* Return buffer format:
/*
* Return buffer format:
* [0-3] "value" is valid flag
* [4-7] value
* [8- ] unknown stuff on newer mobos
@ -310,7 +312,8 @@ static union acpi_object *atk_get_pack_member(struct atk_data *data,
}
/* New package format is:
/*
* New package format is:
* - flag (int)
* class - used for de-muxing the request to the correct GITn
* type (volt, temp, fan)
@ -613,7 +616,8 @@ static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value)
buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
if (buf->flags == 0) {
/* The reading is not valid, possible causes:
/*
* The reading is not valid, possible causes:
* - sensor failure
* - enumeration was FUBAR (and we didn't notice)
*/
@ -1311,14 +1315,16 @@ static int atk_probe_if(struct atk_data *data)
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
/*
* 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)
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)

View File

@ -1,22 +1,22 @@
/*
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.
*/
* 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 <linux/kernel.h>
#include <linux/init.h>
@ -48,7 +48,7 @@ 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 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[] = {
@ -83,7 +83,7 @@ struct atxp1_data {
u8 vrm; /* Detected CPU VRM */
};
static struct atxp1_data * atxp1_update_device(struct device *dev)
static struct atxp1_data *atxp1_update_device(struct device *dev)
{
struct i2c_client *client;
struct atxp1_data *data;
@ -97,7 +97,8 @@ static struct atxp1_data * atxp1_update_device(struct device *dev)
/* 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.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);
@ -106,33 +107,41 @@ static struct atxp1_data * atxp1_update_device(struct device *dev)
mutex_unlock(&data->update_lock);
return(data);
return data;
}
/* sys file functions for cpu0_vid */
static ssize_t atxp1_showvcore(struct device *dev, struct device_attribute *attr, char *buf)
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));
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)
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 int vcore;
unsigned long vcore;
int err;
client = to_i2c_client(dev);
data = atxp1_update_device(dev);
vcore = simple_strtoul(buf, NULL, 10);
err = kstrtoul(buf, 10, &vcore);
if (err)
return err;
vcore /= 25;
vcore *= 25;
@ -144,7 +153,10 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
return -1;
}
/* If output enabled, use control register value. Otherwise original CPU VID */
/*
* If output enabled, use control register value.
* Otherwise original CPU VID
*/
if (data->reg.vid & ATXP1_VIDENA)
cvid = data->reg.vid & ATXP1_VIDMASK;
else
@ -154,18 +166,17 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
if (vid == cvid)
return count;
dev_dbg(dev, "Setting VCore to %d mV (0x%02x)\n", vcore, vid);
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);
}
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;
@ -173,13 +184,16 @@ static ssize_t atxp1_storevcore(struct device *dev, struct device_attribute *att
return count;
}
/* CPU core reference voltage
unit: millivolt
*/
static DEVICE_ATTR(cpu0_vid, S_IRUGO | S_IWUSR, atxp1_showvcore, atxp1_storevcore);
/*
* 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)
static ssize_t atxp1_showgpio1(struct device *dev,
struct device_attribute *attr, char *buf)
{
int size;
struct atxp1_data *data;
@ -191,21 +205,26 @@ static ssize_t atxp1_showgpio1(struct device *dev, struct device_attribute *attr
return size;
}
static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *attr, const char*buf, size_t count)
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 int value;
unsigned long value;
int err;
client = to_i2c_client(dev);
data = atxp1_update_device(dev);
value = simple_strtoul(buf, NULL, 16);
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", value);
dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value);
i2c_smbus_write_byte_data(client, ATXP1_GPIO1, value);
@ -215,13 +234,15 @@ static ssize_t atxp1_storegpio1(struct device *dev, struct device_attribute *att
return count;
}
/* GPIO1 data register
unit: Four bit as hex (e.g. 0x0f)
*/
/*
* 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)
static ssize_t atxp1_showgpio2(struct device *dev,
struct device_attribute *attr, char *buf)
{
int size;
struct atxp1_data *data;
@ -233,19 +254,22 @@ static ssize_t atxp1_showgpio2(struct device *dev, struct device_attribute *attr
return size;
}
static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
static ssize_t atxp1_storegpio2(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct atxp1_data *data;
struct i2c_client *client;
unsigned int value;
struct atxp1_data *data = atxp1_update_device(dev);
struct i2c_client *client = to_i2c_client(dev);
unsigned long value;
int err;
client = to_i2c_client(dev);
data = atxp1_update_device(dev);
value = simple_strtoul(buf, NULL, 16) & 0xff;
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", value);
dev_info(dev, "Writing 0x%x to GPIO1.\n", (unsigned int)value);
i2c_smbus_write_byte_data(client, ATXP1_GPIO2, value);
@ -255,9 +279,10 @@ static ssize_t atxp1_storegpio2(struct device *dev, struct device_attribute *att
return count;
}
/* GPIO2 data register
unit: Eight bit as hex (e.g. 0xff)
*/
/*
* 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[] = {
@ -290,8 +315,10 @@ static int atxp1_detect(struct i2c_client *new_client,
(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 */
/*
* 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) &&
@ -333,7 +360,8 @@ static int atxp1_probe(struct i2c_client *new_client,
mutex_init(&data->update_lock);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group)))
err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
@ -357,7 +385,7 @@ exit:
static int atxp1_remove(struct i2c_client *client)
{
struct atxp1_data * data = i2c_get_clientdata(client);
struct atxp1_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &atxp1_group);
@ -367,15 +395,4 @@ static int atxp1_remove(struct i2c_client *client)
return 0;
};
static int __init atxp1_init(void)
{
return i2c_add_driver(&atxp1_driver);
};
static void __exit atxp1_exit(void)
{
i2c_del_driver(&atxp1_driver);
};
module_init(atxp1_init);
module_exit(atxp1_exit);
module_i2c_driver(atxp1_driver);

View File

@ -58,8 +58,8 @@ MODULE_PARM_DESC(tjmax, "TjMax value in degrees Celsius");
#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_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

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,25 @@
/*
ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23
based on lm75.c by Frodo Looijaard <frodol@dds.nl>
Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
the help of Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* ds1621.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Christian W. Zuckschwerdt <zany@triq.net> 2000-11-23
* based on lm75.c by Frodo Looijaard <frodol@dds.nl>
* Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
* the help of Jean Delvare <khali@linux-fr.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
@ -67,7 +67,7 @@ static const u8 DS1621_REG_TEMP[3] = {
/* Conversions */
#define ALARMS_FROM_REG(val) ((val) & \
(DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
(DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
/* Each client has this additional data */
struct ds1621_data {
@ -93,10 +93,10 @@ static void ds1621_init_client(struct i2c_client *client)
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);
}
@ -155,10 +155,15 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
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);
u16 val = LM75_TEMP_TO_REG(simple_strtol(buf, NULL, 10));
long val;
int err;
err = kstrtol(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
data->temp[attr->index] = val;
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);
@ -212,14 +217,17 @@ static int ds1621_detect(struct i2c_client *client,
int conf, temp;
int i;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
| I2C_FUNC_SMBUS_WORD_DATA
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. */
/*
* 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;
@ -254,7 +262,8 @@ static int ds1621_probe(struct i2c_client *client,
ds1621_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
err = sysfs_create_group(&client->dev.kobj, &ds1621_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&client->dev);
@ -265,11 +274,11 @@ static int ds1621_probe(struct i2c_client *client,
return 0;
exit_remove_files:
exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &ds1621_group);
exit_free:
exit_free:
kfree(data);
exit:
exit:
return err;
}
@ -305,20 +314,8 @@ static struct i2c_driver ds1621_driver = {
.address_list = normal_i2c,
};
static int __init ds1621_init(void)
{
return i2c_add_driver(&ds1621_driver);
}
static void __exit ds1621_exit(void)
{
i2c_del_driver(&ds1621_driver);
}
module_i2c_driver(ds1621_driver);
MODULE_AUTHOR("Christian W. Zuckschwerdt <zany@triq.net>");
MODULE_DESCRIPTION("DS1621 driver");
MODULE_LICENSE("GPL");
module_init(ds1621_init);
module_exit(ds1621_exit);

View File

@ -297,19 +297,8 @@ static struct i2c_driver ds620_driver = {
.id_table = ds620_id,
};
static int __init ds620_init(void)
{
return i2c_add_driver(&ds620_driver);
}
static void __exit ds620_exit(void)
{
i2c_del_driver(&ds620_driver);
}
module_i2c_driver(ds620_driver);
MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
MODULE_DESCRIPTION("DS620 driver");
MODULE_LICENSE("GPL");
module_init(ds620_init);
module_exit(ds620_exit);

View File

@ -41,8 +41,10 @@
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. */
/*
* 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;
};
@ -283,8 +285,10 @@ static int emc1403_detect(struct i2c_client *client,
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 */
/*
* Note: 0x25 is the 1404 which is very similar and this
* driver could be extended
*/
default:
return -ENODEV;
}
@ -366,18 +370,7 @@ static struct i2c_driver sensor_emc1403 = {
.address_list = emc1403_address_list,
};
static int __init sensor_emc1403_init(void)
{
return i2c_add_driver(&sensor_emc1403);
}
static void __exit sensor_emc1403_exit(void)
{
i2c_del_driver(&sensor_emc1403);
}
module_init(sensor_emc1403_init);
module_exit(sensor_emc1403_exit);
module_i2c_driver(sensor_emc1403);
MODULE_AUTHOR("Kalhan Trisal <kalhan.trisal@intel.com");
MODULE_DESCRIPTION("emc1403 Thermal Driver");

View File

@ -1,21 +1,21 @@
/*
emc2103.c - Support for SMSC EMC2103
Copyright (c) 2010 SMSC
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.
*/
* emc2103.c - Support for SMSC EMC2103
* Copyright (c) 2010 SMSC
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/module.h>
#include <linux/init.h>
@ -48,12 +48,14 @@ static const u8 REG_TEMP_MAX[4] = { 0x34, 0x30, 0x31, 0x32 };
/* 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
/*
* 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 */
* 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");
@ -302,10 +304,12 @@ show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
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. */
/*
* 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)
{
@ -722,19 +726,8 @@ static struct i2c_driver emc2103_driver = {
.address_list = normal_i2c,
};
static int __init sensors_emc2103_init(void)
{
return i2c_add_driver(&emc2103_driver);
}
static void __exit sensors_emc2103_exit(void)
{
i2c_del_driver(&emc2103_driver);
}
module_i2c_driver(emc2103_driver);
MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>");
MODULE_DESCRIPTION("SMSC EMC2103 hwmon driver");
MODULE_LICENSE("GPL");
module_init(sensors_emc2103_init);
module_exit(sensors_emc2103_exit);

View File

@ -552,17 +552,7 @@ static struct i2c_driver emc6w201_driver = {
.address_list = normal_i2c,
};
static int __init sensors_emc6w201_init(void)
{
return i2c_add_driver(&emc6w201_driver);
}
module_init(sensors_emc6w201_init);
static void __exit sensors_emc6w201_exit(void)
{
i2c_del_driver(&emc6w201_driver);
}
module_exit(sensors_emc6w201_exit);
module_i2c_driver(emc6w201_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("SMSC EMC6W201 hardware monitoring driver");

View File

@ -202,7 +202,7 @@ struct f71805f_sio_data {
static inline long in_from_reg(u8 reg)
{
return (reg * 8);
return reg * 8;
}
/* The 2 least significant bits are not used */
@ -212,13 +212,13 @@ static inline u8 in_to_reg(long val)
return 0;
if (val >= 2016)
return 0xfc;
return (((val + 16) / 32) << 2);
return ((val + 16) / 32) << 2;
}
/* in0 is downscaled by a factor 2 internally */
static inline long in0_from_reg(u8 reg)
{
return (reg * 16);
return reg * 16;
}
static inline u8 in0_to_reg(long val)
@ -227,7 +227,7 @@ static inline u8 in0_to_reg(long val)
return 0;
if (val >= 4032)
return 0xfc;
return (((val + 32) / 64) << 2);
return ((val + 32) / 64) << 2;
}
/* The 4 most significant bits are not used */
@ -236,17 +236,19 @@ static inline long fan_from_reg(u16 reg)
reg &= 0xfff;
if (!reg || reg == 0xfff)
return 0;
return (1500000 / reg);
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 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);
return 1500000 / rpm;
}
static inline unsigned long pwm_freq_from_reg(u8 reg)
@ -278,7 +280,7 @@ static inline int pwm_mode_from_reg(u8 reg)
static inline long temp_from_reg(u8 reg)
{
return (reg * 1000);
return reg * 1000;
}
static inline u8 temp_to_reg(long val)
@ -308,9 +310,11 @@ static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
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 */
/*
* 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;
@ -455,7 +459,12 @@ static ssize_t set_in0_max(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -471,7 +480,12 @@ static ssize_t set_in0_min(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -517,7 +531,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -533,7 +552,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -579,7 +603,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -595,7 +624,12 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -664,7 +698,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
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 = simple_strtoul(buf, NULL, 10);
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
if (val > 255)
return -EINVAL;
@ -685,8 +724,13 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
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 = simple_strtoul(buf, NULL, 10);
u8 reg;
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
if (val < 1 || val > 3)
return -EINVAL;
@ -730,7 +774,12 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
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 = simple_strtoul(buf, NULL, 10);
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);
@ -742,7 +791,7 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
static ssize_t show_pwm_auto_point_temp(struct device *dev,
struct device_attribute *devattr,
char* buf)
char *buf)
{
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
@ -755,13 +804,18 @@ static ssize_t show_pwm_auto_point_temp(struct device *dev,
static ssize_t set_pwm_auto_point_temp(struct device *dev,
struct device_attribute *devattr,
const char* buf, size_t count)
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 = simple_strtol(buf, NULL, 10);
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);
@ -774,7 +828,7 @@ static ssize_t set_pwm_auto_point_temp(struct device *dev,
static ssize_t show_pwm_auto_point_fan(struct device *dev,
struct device_attribute *devattr,
char* buf)
char *buf)
{
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
@ -787,18 +841,23 @@ static ssize_t show_pwm_auto_point_fan(struct device *dev,
static ssize_t set_pwm_auto_point_fan(struct device *dev,
struct device_attribute *devattr,
const char* buf, size_t count)
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 = simple_strtoul(buf, NULL, 10);
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]);
data->auto_points[pwmnr].fan[apnr]);
mutex_unlock(&data->update_lock);
return count;
@ -851,7 +910,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -867,7 +931,12 @@ static ssize_t set_temp_hyst(struct device *dev, struct device_attribute
struct f71805f_data *data = dev_get_drvdata(dev);
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
int nr = attr->index;
long val = simple_strtol(buf, NULL, 10);
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);
@ -920,9 +989,9 @@ static ssize_t show_name(struct device *dev, struct device_attribute
}
static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL, 0);
static SENSOR_DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR,
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,
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,
@ -1010,8 +1079,10 @@ 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 */
/*
* 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);
@ -1246,8 +1317,10 @@ static const struct attribute_group f71805f_group_optin[4] = {
{ .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) */
/*
* 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,
@ -1282,13 +1355,17 @@ static void __devinit f71805f_init_device(struct f71805f_data *data)
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. */
/*
* 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 */
/*
* 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),
@ -1304,12 +1381,13 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
struct resource *res;
int i, err;
static const char *names[] = {
static const char * const names[] = {
"f71805f",
"f71872f",
};
if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
pr_err("Out of memory\n");
goto exit;
@ -1347,40 +1425,47 @@ static int __devinit f71805f_probe(struct platform_device *pdev)
f71805f_init_device(data);
/* Register sysfs interface files */
if ((err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group)))
err = sysfs_create_group(&pdev->dev.kobj, &f71805f_group);
if (err)
goto exit_release_region;
if (data->has_in & (1 << 4)) { /* in4 */
if ((err = sysfs_create_group(&pdev->dev.kobj,
&f71805f_group_optin[0])))
err = sysfs_create_group(&pdev->dev.kobj,
&f71805f_group_optin[0]);
if (err)
goto exit_remove_files;
}
if (data->has_in & (1 << 8)) { /* in8 */
if ((err = sysfs_create_group(&pdev->dev.kobj,
&f71805f_group_optin[1])))
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) */
if ((err = sysfs_create_group(&pdev->dev.kobj,
&f71805f_group_optin[2])))
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) */
if ((err = sysfs_create_group(&pdev->dev.kobj,
&f71805f_group_optin[3])))
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)) {
if ((err = sysfs_create_file(&pdev->dev.kobj,
f71805f_attributes_pwm_freq[i])))
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) {
if ((err = sysfs_chmod_file(&pdev->dev.kobj,
f71805f_attr_pwm[i],
S_IRUGO | S_IWUSR))) {
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;
@ -1495,7 +1580,7 @@ static int __init f71805f_find(int sioaddr, unsigned short *address,
int err = -ENODEV;
u16 devid;
static const char *names[] = {
static const char * const names[] = {
"F71805F/FG",
"F71872F/FG or F71806F/FG",
};

View File

@ -112,7 +112,7 @@ 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 *f71882fg_names[] = {
static const char *const f71882fg_names[] = {
"f71808e",
"f71808a",
"f71858fg",
@ -252,9 +252,11 @@ struct f71882fg_data {
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 */
/*
* 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];
@ -362,7 +364,7 @@ static ssize_t store_pwm_auto_point_temp(struct device *dev,
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 __devinit f71882fg_probe(struct platform_device *pdev);
static int f71882fg_remove(struct platform_device *pdev);
static struct platform_driver f71882fg_driver = {
@ -376,8 +378,10 @@ static struct platform_driver f71882fg_driver = {
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) */
/*
* 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,
@ -424,9 +428,11 @@ static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
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. */
/*
* 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),
@ -485,10 +491,11 @@ static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
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
/*
* 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),
@ -603,8 +610,10 @@ static struct sensor_device_attribute_2 fxxxx_fan_beep_attr[] = {
store_fan_beep, 0, 3),
};
/* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
standard models */
/*
* 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,
@ -673,9 +682,11 @@ static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[3][7] = { {
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 */
/*
* 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,
@ -925,9 +936,11 @@ 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 */
/*
* 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,
@ -2295,8 +2308,10 @@ static int __devinit f71882fg_probe(struct platform_device *pdev)
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 */
/*
* 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));

View File

@ -917,19 +917,8 @@ static int f75375_detect(struct i2c_client *client,
return 0;
}
static int __init sensors_f75375_init(void)
{
return i2c_add_driver(&f75375_driver);
}
static void __exit sensors_f75375_exit(void)
{
i2c_del_driver(&f75375_driver);
}
module_i2c_driver(f75375_driver);
MODULE_AUTHOR("Riku Voipio");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("F75373/F75375/F75387 hardware monitoring driver");
module_init(sensors_f75375_init);
module_exit(sensors_f75375_exit);

View File

@ -1,4 +1,5 @@
/* fschmd.c
/*
* fschmd.c
*
* Copyright (C) 2007 - 2009 Hans de Goede <hdegoede@redhat.com>
*
@ -76,12 +77,12 @@ enum chips { fscpos, fscher, fscscy, fschrc, fschmd, fschds, fscsyl };
#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 };
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 */
@ -103,10 +104,12 @@ static const u8 FSCHMD_REG_VOLT[7][6] = {
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. */
/*
* 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 */
@ -182,11 +185,13 @@ static const u8 FSCHMD_REG_TEMP_STATE[7][11] = {
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?? */
/*
* 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 */
@ -198,13 +203,15 @@ static const u8 FSCHMD_REG_TEMP_LIMIT[7][11] = {
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 }; */
/*
* 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 };
@ -290,24 +297,30 @@ struct fschmd_data {
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. */
/*
* 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. */
/*
* 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 */
/*
* 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);
@ -359,9 +372,14 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute
{
int index = to_sensor_dev_attr(devattr)->index;
struct fschmd_data *data = dev_get_drvdata(dev);
long v = simple_strtol(buf, NULL, 10) / 1000;
long v;
int err;
v = SENSORS_LIMIT(v, -128, 127) + 128;
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),
@ -427,12 +445,23 @@ static ssize_t store_fan_div(struct device *dev, struct device_attribute
int index = to_sensor_dev_attr(devattr)->index;
struct fschmd_data *data = dev_get_drvdata(dev);
/* supported values: 2, 4, 8 */
unsigned long v = simple_strtoul(buf, NULL, 10);
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;
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);
@ -502,7 +531,12 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
{
int index = to_sensor_dev_attr(devattr)->index;
struct fschmd_data *data = dev_get_drvdata(dev);
unsigned long v = simple_strtoul(buf, NULL, 10);
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) {
@ -522,8 +556,10 @@ static ssize_t store_pwm_auto_point1_pwm(struct device *dev,
}
/* 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 */
/*
* 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)
{
@ -540,7 +576,12 @@ static ssize_t store_alert_led(struct device *dev,
{
u8 reg;
struct fschmd_data *data = dev_get_drvdata(dev);
unsigned long v = simple_strtoul(buf, NULL, 10);
unsigned long v;
int err;
err = kstrtoul(buf, 10, &v);
if (err)
return err;
mutex_lock(&data->update_lock);
@ -754,8 +795,10 @@ static int watchdog_stop(struct fschmd_data *data)
}
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) */
/*
* 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);
@ -769,10 +812,12 @@ 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. */
/*
* 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) {
@ -847,7 +892,8 @@ static ssize_t watchdog_write(struct file *filp, const char __user *buf,
return count;
}
static long watchdog_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
static long watchdog_ioctl(struct file *filp, unsigned int cmd,
unsigned long arg)
{
struct watchdog_info ident = {
.options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
@ -930,30 +976,38 @@ static const struct file_operations watchdog_fops = {
* 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. */
/*
* 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 */
/*
* 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 */
/*
* 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 */
/*
* 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) {
@ -988,9 +1042,11 @@ static void fschmd_dmi_decode(const struct dmi_header *header, void *dummy)
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 */
/*
* 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];
@ -1058,15 +1114,19 @@ static int fschmd_probe(struct i2c_client *client,
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) */
/*
* 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 */
/*
* 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;
@ -1157,9 +1217,11 @@ static int fschmd_probe(struct i2c_client *client,
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) */
/*
* 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 */
@ -1225,8 +1287,10 @@ static int fschmd_remove(struct i2c_client *client)
mutex_unlock(&data->watchdog_lock);
}
/* Check if registered in case we're called from fschmd_detect
to cleanup after an error */
/*
* 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);
@ -1269,8 +1333,10 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
client,
FSCHMD_REG_TEMP_LIMIT[data->kind][i]);
/* reset alarm if the alarm condition is gone,
the chip doesn't do this itself */
/*
* 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])
@ -1314,20 +1380,9 @@ static struct fschmd_data *fschmd_update_device(struct device *dev)
return data;
}
static int __init fschmd_init(void)
{
return i2c_add_driver(&fschmd_driver);
}
static void __exit fschmd_exit(void)
{
i2c_del_driver(&fschmd_driver);
}
module_i2c_driver(fschmd_driver);
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
MODULE_DESCRIPTION("FSC Poseidon, Hermes, Scylla, Heracles, Heimdall, Hades "
"and Syleus driver");
MODULE_LICENSE("GPL");
module_init(fschmd_init);
module_exit(fschmd_exit);

View File

@ -1,17 +1,17 @@
/*
g760a - Driver for the Global Mixed-mode Technology Inc. G760A
fan speed PWM controller chip
Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
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.
*/
* g760a - Driver for the Global Mixed-mode Technology Inc. G760A
* fan speed PWM controller chip
*
* Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
*
* 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 <linux/module.h>
#include <linux/init.h>
@ -59,7 +59,8 @@ struct g760a_data {
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 */
* bit 1: set when fan speed below 1920 rpm
*/
};
#define G760A_DEFAULT_CLK 32768
@ -99,7 +100,7 @@ static int g760a_write_value(struct i2c_client *client, enum g760a_regs reg,
return i2c_smbus_write_byte_data(client, reg, value);
}
/****************************************************************************
/*
* sysfs attributes
*/
@ -192,7 +193,7 @@ static const struct attribute_group g760a_group = {
.attrs = g760a_attributes,
};
/****************************************************************************
/*
* new-style driver model code
*/
@ -250,21 +251,8 @@ static int g760a_remove(struct i2c_client *client)
return 0;
}
/* module management */
static int __init g760a_init(void)
{
return i2c_add_driver(&g760a_driver);
}
static void __exit g760a_exit(void)
{
i2c_del_driver(&g760a_driver);
}
module_i2c_driver(g760a_driver);
MODULE_AUTHOR("Herbert Valerio Riedel <hvr@gnu.org>");
MODULE_DESCRIPTION("GMT G760A driver");
MODULE_LICENSE("GPL");
module_init(g760a_init);
module_exit(g760a_exit);

View File

@ -83,11 +83,12 @@ enum chips { gl518sm_r00, gl518sm_r80 };
#define RAW_FROM_REG(val) val
#define BOOL_FROM_REG(val) ((val)?0:1)
#define BOOL_TO_REG(val) ((val)?0:1)
#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_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)
@ -98,13 +99,13 @@ static inline u8 FAN_TO_REG(long rpm, int div)
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 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 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 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))
@ -169,7 +170,8 @@ static struct i2c_driver gl518_driver = {
*/
#define show(type, suffix, value) \
static ssize_t show_##suffix(struct device *dev, struct device_attribute *attr, char *buf) \
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)); \
@ -222,12 +224,16 @@ static ssize_t show_fan_div(struct device *dev,
}
#define set(type, suffix, value, reg) \
static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \
size_t count) \
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 = simple_strtol(buf, NULL, 10); \
long val; \
int err = kstrtol(buf, 10, &val); \
if (err) \
return err; \
\
mutex_lock(&data->update_lock); \
data->value = type##_TO_REG(val); \
@ -237,13 +243,17 @@ static ssize_t set_##suffix(struct device *dev, struct device_attribute *attr, c
}
#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) \
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 = simple_strtoul(buf, NULL, 10); \
unsigned long val; \
int err = kstrtoul(buf, 10, &val); \
if (err) \
return err; \
\
mutex_lock(&data->update_lock); \
regvalue = gl518_read_value(client, reg); \
@ -280,7 +290,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct gl518_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int regvalue;
unsigned long val = simple_strtoul(buf, NULL, 10);
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);
@ -308,13 +323,26 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
struct gl518_data *data = i2c_get_clientdata(client);
int nr = to_sensor_dev_attr(attr)->index;
int regvalue;
unsigned long val = simple_strtoul(buf, NULL, 10);
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;
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);
@ -395,8 +423,12 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
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;
bit = simple_strtoul(buf, NULL, 10);
if (bit & ~1)
return -EINVAL;
@ -528,12 +560,14 @@ static int gl518_probe(struct i2c_client *client,
gl518_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &gl518_group)))
err = sysfs_create_group(&client->dev.kobj, &gl518_group);
if (err)
goto exit_free;
if (data->type == gl518sm_r80)
if ((err = sysfs_create_group(&client->dev.kobj,
&gl518_group_r80)))
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)) {
@ -554,8 +588,10 @@ exit:
}
/* Called when we have found a new GL518SM.
Note that we preserve D4:NoFan2 and D2:beep_enable. */
/*
* 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 */
@ -585,9 +621,11 @@ static int gl518_remove(struct i2c_client *client)
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. */
/*
* 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))
@ -676,21 +714,10 @@ static struct gl518_data *gl518_update_device(struct device *dev)
return data;
}
static int __init sensors_gl518sm_init(void)
{
return i2c_add_driver(&gl518_driver);
}
static void __exit sensors_gl518sm_exit(void)
{
i2c_del_driver(&gl518_driver);
}
module_i2c_driver(gl518_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"Kyosti Malkki <kmalkki@cc.hut.fi> and "
"Hong-Gunn Chew <hglinux@gunnet.org>");
MODULE_DESCRIPTION("GL518SM driver");
MODULE_LICENSE("GPL");
module_init(sensors_gl518sm_init);
module_exit(sensors_gl518sm_exit);

View File

@ -1,25 +1,25 @@
/*
gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
Kyösti Mälkki <kmalkki@cc.hut.fi>
Copyright (c) 2005 Maarten Deprez <maartendeprez@users.sourceforge.net>
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.
*/
* gl520sm.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>,
* Kyösti Mälkki <kmalkki@cc.hut.fi>
* Copyright (c) 2005 Maarten Deprez <maartendeprez@users.sourceforge.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
#include <linux/module.h>
#include <linux/init.h>
@ -41,10 +41,11 @@ MODULE_PARM_DESC(extra_sensor_type, "Type of extra sensor (0=autodetect, 1=tempe
/* 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
*/
/*
* 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
@ -142,11 +143,11 @@ static ssize_t get_cpu_vid(struct device *dev, struct device_attribute *attr,
}
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 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))
#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)
@ -193,8 +194,13 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
u8 r;
long v;
int err;
err = kstrtol(buf, 10, &v);
if (err)
return err;
mutex_lock(&data->update_lock);
@ -222,8 +228,13 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
u8 r;
long v;
int err;
err = kstrtol(buf, 10, &v);
if (err)
return err;
if (n == 0)
r = VDD_TO_REG(v);
@ -272,8 +283,10 @@ 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))
#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)
@ -317,8 +330,13 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct gl520_data *data = i2c_get_clientdata(client);
int n = to_sensor_dev_attr(attr)->index;
unsigned long v = simple_strtoul(buf, NULL, 10);
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]);
@ -351,16 +369,30 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
struct i2c_client *client = to_i2c_client(dev);
struct gl520_data *data = i2c_get_clientdata(client);
int n = to_sensor_dev_attr(attr)->index;
unsigned long v = simple_strtoul(buf, NULL, 10);
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;
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);
dev_err(&client->dev,
"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n", v);
return -EINVAL;
}
@ -385,7 +417,15 @@ static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr,
{
struct i2c_client *client = to_i2c_client(dev);
struct gl520_data *data = i2c_get_clientdata(client);
u8 r = simple_strtoul(buf, NULL, 10)?1:0;
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;
@ -410,7 +450,8 @@ 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))
#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)
@ -430,8 +471,8 @@ static ssize_t get_temp_max(struct device *dev, struct device_attribute *attr,
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)
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);
@ -445,7 +486,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -460,7 +506,12 @@ static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute
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 = simple_strtol(buf, NULL, 10);
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);
@ -507,7 +558,15 @@ static ssize_t set_beep_enable(struct device *dev, struct device_attribute
{
struct i2c_client *client = to_i2c_client(dev);
struct gl520_data *data = i2c_get_clientdata(client);
u8 r = simple_strtoul(buf, NULL, 10)?0:1;
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;
@ -523,7 +582,12 @@ static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr,
{
struct i2c_client *client = to_i2c_client(dev);
struct gl520_data *data = i2c_get_clientdata(client);
u8 r = simple_strtoul(buf, NULL, 10);
unsigned long r;
int err;
err = kstrtoul(buf, 10, &r);
if (err)
return err;
mutex_lock(&data->update_lock);
r &= data->alarm_mask;
@ -575,7 +639,11 @@ static ssize_t set_beep(struct device *dev, struct device_attribute *attr,
int bitnr = to_sensor_dev_attr(attr)->index;
unsigned long bit;
bit = simple_strtoul(buf, NULL, 10);
int err;
err = kstrtoul(buf, 10, &bit);
if (err)
return err;
if (bit & ~1)
return -EINVAL;
@ -652,13 +720,16 @@ static const struct attribute_group gl520_group = {
.attrs = gl520_attributes,
};
static struct attribute *gl520_attributes_opt[] = {
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,
@ -667,8 +738,12 @@ static struct attribute *gl520_attributes_opt[] = {
NULL
};
static const struct attribute_group gl520_group_opt = {
.attrs = gl520_attributes_opt,
static const struct attribute_group gl520_group_in4 = {
.attrs = gl520_attributes_in4,
};
static const struct attribute_group gl520_group_temp2 = {
.attrs = gl520_attributes_temp2,
};
@ -717,35 +792,17 @@ static int gl520_probe(struct i2c_client *client,
gl520_init_client(client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&client->dev.kobj, &gl520_group)))
err = sysfs_create_group(&client->dev.kobj, &gl520_group);
if (err)
goto exit_free;
if (data->two_temps) {
if ((err = device_create_file(&client->dev,
&sensor_dev_attr_temp2_input.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_temp2_max.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_temp2_max_hyst.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_temp2_alarm.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_temp2_beep.dev_attr)))
goto exit_remove_files;
} else {
if ((err = device_create_file(&client->dev,
&sensor_dev_attr_in4_input.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_in4_min.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_in4_max.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_in4_alarm.dev_attr))
|| (err = device_create_file(&client->dev,
&sensor_dev_attr_in4_beep.dev_attr)))
goto exit_remove_files;
}
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)) {
@ -757,7 +814,8 @@ static int gl520_probe(struct i2c_client *client,
exit_remove_files:
sysfs_remove_group(&client->dev.kobj, &gl520_group);
sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
sysfs_remove_group(&client->dev.kobj, &gl520_group_in4);
sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2);
exit_free:
kfree(data);
exit:
@ -809,15 +867,18 @@ static int gl520_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &gl520_group);
sysfs_remove_group(&client->dev.kobj, &gl520_group_opt);
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 */
/*
* 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))
@ -849,7 +910,8 @@ static struct gl520_data *gl520_update_device(struct device *dev)
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;
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,
@ -910,23 +972,10 @@ static struct gl520_data *gl520_update_device(struct device *dev)
return data;
}
static int __init sensors_gl520sm_init(void)
{
return i2c_add_driver(&gl520_driver);
}
static void __exit sensors_gl520sm_exit(void)
{
i2c_del_driver(&gl520_driver);
}
module_i2c_driver(gl520_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
"Kyösti Mälkki <kmalkki@cc.hut.fi>, "
"Maarten Deprez <maartendeprez@users.sourceforge.net>");
MODULE_DESCRIPTION("GL520SM driver");
MODULE_LICENSE("GPL");
module_init(sensors_gl520sm_init);
module_exit(sensors_gl520sm_exit);

View File

@ -40,7 +40,7 @@
* 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
* 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:
@ -83,27 +83,27 @@ int vid_from_reg(int val, u8 vrm)
{
int vid;
switch(vrm) {
switch (vrm) {
case 100: /* VRD 10.0 */
case 100: /* VRD 10.0 */
/* compute in uV, round to mV */
val &= 0x3f;
if((val & 0x1f) == 0x1f)
if ((val & 0x1f) == 0x1f)
return 0;
if((val & 0x1f) <= 0x09 || val == 0x0a)
if ((val & 0x1f) <= 0x09 || val == 0x0a)
vid = 1087500 - (val & 0x1f) * 25000;
else
vid = 1862500 - (val & 0x1f) * 25000;
if(val & 0x20)
if (val & 0x20)
vid -= 12500;
return((vid + 500) / 1000);
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);
return (1600000 - (val - 2) * 6250 + 500) / 1000;
case 24: /* Athlon64 & Opteron */
val &= 0x1f;
@ -118,38 +118,38 @@ int vid_from_reg(int val, u8 vrm)
case 91: /* VRM 9.1 */
case 90: /* VRM 9.0 */
val &= 0x1f;
return(val == 0x1f ? 0 :
1850 - val * 25);
return val == 0x1f ? 0 :
1850 - val * 25;
case 85: /* VRM 8.5 */
val &= 0x1f;
return((val & 0x10 ? 25 : 0) +
return (val & 0x10 ? 25 : 0) +
((val & 0x0f) > 0x04 ? 2050 : 1250) -
((val & 0x0f) * 50));
((val & 0x0f) * 50);
case 84: /* VRM 8.4 */
val &= 0x0f;
/* fall through */
case 82: /* VRM 8.2 */
val &= 0x1f;
return(val == 0x1f ? 0 :
return val == 0x1f ? 0 :
val & 0x10 ? 5100 - (val) * 100 :
2050 - (val) * 50);
2050 - (val) * 50;
case 17: /* Intel IMVP-II */
val &= 0x1f;
return(val & 0x10 ? 975 - (val & 0xF) * 25 :
1750 - val * 50);
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);
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);
return val > 0x77 ? 0 : (1500000 - (val * 12500) + 500) / 1000;
default: /* report 0 for unknown */
if (vrm)
pr_warn("Requested unsupported VRM version (%u)\n",
@ -157,7 +157,7 @@ int vid_from_reg(int val, u8 vrm)
return 0;
}
}
EXPORT_SYMBOL(vid_from_reg);
/*
* After this point is the code to automatically determine which
@ -166,9 +166,10 @@ int vid_from_reg(int val, u8 vrm)
struct vrm_model {
u8 vendor;
u8 eff_family;
u8 eff_model;
u8 eff_stepping;
u8 family;
u8 model_from;
u8 model_to;
u8 stepping_to;
u8 vrm_type;
};
@ -177,42 +178,52 @@ struct vrm_model {
#ifdef CONFIG_X86
/*
* The stepping parameter is highest acceptable stepping for current line.
* 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, ANY, ANY, 90}, /* Athlon Duron etc */
{X86_VENDOR_AMD, 0xF, 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, 0x7F, ANY, 24}, /* NPT family 0Fh */
{X86_VENDOR_AMD, 0xF, ANY, ANY, 25}, /* future fam. 0Fh */
{X86_VENDOR_AMD, 0x10, ANY, ANY, 25}, /* NPT family 10h */
{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, 0x9, ANY, 13}, /* Pentium M (130 nm) */
{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85}, /* Tualatin */
{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13}, /* Pentium M (90 nm) */
{X86_VENDOR_INTEL, 0x6, 0xE, ANY, 14}, /* Intel Core (65 nm) */
{X86_VENDOR_INTEL, 0x6, 0xF, ANY, 110}, /* Intel Conroe */
{X86_VENDOR_INTEL, 0x6, ANY, ANY, 82}, /* any P6 */
{X86_VENDOR_INTEL, 0xF, 0x0, ANY, 90}, /* P4 */
{X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90}, /* P4 Willamette */
{X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90}, /* P4 Northwood */
{X86_VENDOR_INTEL, 0xF, ANY, ANY, 100}, /* Prescott and above assume VRD 10 */
{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, ANY, 85}, /* Eden ESP/Ezra */
{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85}, /* Ezra T */
{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85}, /* Nehemiah */
{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17}, /* C3-M, Eden-N */
{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0}, /* No information */
{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13}, /* C7-M, C7, Eden (Esther) */
{X86_VENDOR_CENTAUR, 0x6, 0xD, ANY, 134}, /* C7-D, C7-M, C7, Eden (Esther) */
{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0} /* stop here */
{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) */
};
/*
@ -248,20 +259,17 @@ static u8 get_via_model_d_vrm(void)
}
}
static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
static u8 find_vrm(u8 family, u8 model, u8 stepping, u8 vendor)
{
int i = 0;
int i;
while (vrm_models[i].vendor!=X86_VENDOR_UNKNOWN) {
if (vrm_models[i].vendor==vendor)
if ((vrm_models[i].eff_family==eff_family)
&& ((vrm_models[i].eff_model==eff_model) ||
(vrm_models[i].eff_model >= 0x10 &&
eff_model <= vrm_models[i].eff_model) ||
(vrm_models[i].eff_model==ANY)) &&
(eff_stepping <= vrm_models[i].eff_stepping))
return vrm_models[i].vrm_type;
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;
@ -270,21 +278,12 @@ static u8 find_vrm(u8 eff_family, u8 eff_model, u8 eff_stepping, u8 vendor)
u8 vid_which_vrm(void)
{
struct cpuinfo_x86 *c = &cpu_data(0);
u32 eax;
u8 eff_family, eff_model, eff_stepping, vrm_ret;
u8 vrm_ret;
if (c->x86 < 6) /* Any CPU with family lower than 6 */
return 0; /* doesn't have VID and/or CPUID */
return 0; /* doesn't have VID */
eax = cpuid_eax(1);
eff_family = ((eax & 0x00000F00)>>8);
eff_model = ((eax & 0x000000F0)>>4);
eff_stepping = eax & 0xF;
if (eff_family == 0xF) { /* use extended model & family */
eff_family += ((eax & 0x00F00000)>>20);
eff_model += ((eax & 0x000F0000)>>16)<<4;
}
vrm_ret = find_vrm(eff_family, eff_model, eff_stepping, c->x86_vendor);
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)
@ -300,8 +299,6 @@ u8 vid_which_vrm(void)
return 0;
}
#endif
EXPORT_SYMBOL(vid_from_reg);
EXPORT_SYMBOL(vid_which_vrm);
MODULE_AUTHOR("Rudolf Marek <r.marek@assembler.cz>");

View File

@ -1,14 +1,14 @@
/*
hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
This file defines the sysfs class "hwmon", for use by sensors drivers.
Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
*/
* hwmon.c - part of lm_sensors, Linux kernel modules for hardware monitoring
*
* This file defines the sysfs class "hwmon", for use by sensors drivers.
*
* Copyright (C) 2005 Mark M. Hoffman <mhoffman@lightlink.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@ -55,6 +55,7 @@ struct device *hwmon_device_register(struct device *dev)
return hwdev;
}
EXPORT_SYMBOL_GPL(hwmon_device_register);
/**
* hwmon_device_unregister - removes the previously registered class device
@ -72,6 +73,7 @@ void hwmon_device_unregister(struct device *dev)
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)
{
@ -119,9 +121,6 @@ static void __exit hwmon_exit(void)
subsys_initcall(hwmon_init);
module_exit(hwmon_exit);
EXPORT_SYMBOL_GPL(hwmon_device_register);
EXPORT_SYMBOL_GPL(hwmon_device_unregister);
MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
MODULE_DESCRIPTION("hardware monitoring sysfs/class support");
MODULE_LICENSE("GPL");

View File

@ -159,8 +159,12 @@ static ssize_t store_amb_min(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i5k_amb_data *data = dev_get_drvdata(dev);
unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
unsigned long temp;
int ret = kstrtoul(buf, 10, &temp);
if (ret < 0)
return ret;
temp = temp / 500;
if (temp > 255)
temp = 255;
@ -175,8 +179,12 @@ static ssize_t store_amb_mid(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i5k_amb_data *data = dev_get_drvdata(dev);
unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
unsigned long temp;
int ret = kstrtoul(buf, 10, &temp);
if (ret < 0)
return ret;
temp = temp / 500;
if (temp > 255)
temp = 255;
@ -191,8 +199,12 @@ static ssize_t store_amb_max(struct device *dev,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i5k_amb_data *data = dev_get_drvdata(dev);
unsigned long temp = simple_strtoul(buf, NULL, 10) / 500;
unsigned long temp;
int ret = kstrtoul(buf, 10, &temp);
if (ret < 0)
return ret;
temp = temp / 500;
if (temp > 255)
temp = 255;

View File

@ -1045,7 +1045,7 @@ static struct aem_ro_sensor_template aem2_ro_sensors[] = {
{"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},
{"power3_average", aem2_show_pcap_value, POWER_AUX},
{"power_cap", aem2_show_pcap_value, POWER_CAP},
{NULL, NULL, 0},
};

View File

@ -176,12 +176,16 @@ static bool fix_pwm_polarity;
#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. */
/*
* 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. */
/*
* 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
@ -227,8 +231,10 @@ struct it87_sio_data {
u8 skip_pwm;
};
/* For each registered chip, we need to keep some data in memory.
The structure is dynamically allocated. */
/*
* 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;
@ -259,14 +265,16 @@ struct it87_data {
u8 fan_main_ctrl; /* Register value */
u8 fan_ctl; /* Register value */
/* The following 3 arrays correspond to the same registers up to
/*
* 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. */
* 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) */
@ -388,9 +396,11 @@ static const unsigned int pwm_freq[8] = {
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 16bit tachometer support. */
/*
* 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
@ -402,9 +412,11 @@ static inline int has_16bit_fans(const struct it87_data *data)
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. */
/*
* 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);
}
@ -606,10 +618,8 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *attr,
{
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 the value is updated while
we use it */
u8 reg = data->sensor; /* In case value is updated while used */
if (reg & (1 << nr))
return sprintf(buf, "3\n"); /* thermal diode */
@ -894,8 +904,10 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
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 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;
@ -905,8 +917,10 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
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 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),
@ -965,8 +979,10 @@ static ssize_t set_pwm_temp_map(struct device *dev,
long val;
u8 reg;
/* This check can go away if we ever support automatic fan speed
control on newer chips. */
/*
* 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;
@ -991,8 +1007,10 @@ static ssize_t set_pwm_temp_map(struct device *dev,
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 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]);
@ -1162,9 +1180,11 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
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. */
/*
* 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, \
@ -1321,12 +1341,12 @@ 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 *labels[] = {
static const char * const labels[] = {
"+5V",
"5VSB",
"Vbat",
};
static const char *labels_it8721[] = {
static const char * const labels_it8721[] = {
"+3.3V",
"3VSB",
"Vbat",
@ -1736,12 +1756,14 @@ static int __init it87_find(unsigned short *address,
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. */
/*
* 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);
}
@ -1793,7 +1815,7 @@ static int __devinit it87_probe(struct platform_device *pdev)
int err = 0, i;
int enable_pwm_interface;
int fan_beep_need_rw;
static const char *names[] = {
static const char * const names[] = {
"it87",
"it8712",
"it8716",
@ -1879,9 +1901,11 @@ static int __devinit it87_probe(struct platform_device *pdev)
if (!fan_beep_need_rw)
continue;
/* As we have a single beep enable bit for all fans,
/*
* As we have a single beep enable bit for all fans,
* only the first enabled fan has a writable attribute
* for it. */
* for it.
*/
if (sysfs_chmod_file(&dev->kobj,
it87_attributes_fan_beep[i],
S_IRUGO | S_IWUSR))
@ -1961,18 +1985,22 @@ static int __devexit it87_remove(struct platform_device *pdev)
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. */
/*
* 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. */
/*
* 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);
@ -1983,15 +2011,19 @@ static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
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
/*
* 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. */
* 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.
/*
* The user asks us to attempt a chip reconfiguration.
* This means switching to active high polarity and
* inverting all fan speed values. */
* inverting all fan speed values.
*/
int i;
u8 pwm[3];
@ -1999,10 +2031,12 @@ static int __devinit it87_check_pwm(struct device *dev)
pwm[i] = it87_read_value(data,
IT87_REG_PWM(i));
/* If any fan is in automatic pwm mode, the polarity
/*
* 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). */
* PWM interface).
*/
if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
dev_info(dev, "Reconfiguring PWM to "
"active high polarity\n");
@ -2038,7 +2072,8 @@ static void __devinit it87_init_device(struct platform_device *pdev)
int tmp, i;
u8 mask;
/* For each PWM channel:
/*
* 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
@ -2048,18 +2083,21 @@ static void __devinit it87_init_device(struct platform_device *pdev)
* 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. */
* 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
/*
* 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. */
* 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)
@ -2071,10 +2109,12 @@ static void __devinit it87_init_device(struct platform_device *pdev)
it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127);
}
/* Temperature channels are not forcibly enabled, as they can be
/*
* 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. */
* 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);
@ -2157,8 +2197,10 @@ static struct it87_data *it87_update_device(struct device *dev)
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 */
/*
* 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);
}
@ -2220,13 +2262,17 @@ static struct it87_data *it87_update_device(struct device *dev)
it87_update_pwm_ctrl(data, i);
data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
/* The 8705 does not have VID capability.
The 8718 and later don't use IT87_REG_VID for the
same purpose. */
/*
* 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. */
/*
* 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;

View File

@ -180,25 +180,7 @@ 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[] = {
{ "adt7408", 0 },
{ "at30ts00", 0 },
{ "cat94ts02", 0 },
{ "cat6095", 0 },
{ "jc42", 0 },
{ "max6604", 0 },
{ "mcp9804", 0 },
{ "mcp9805", 0 },
{ "mcp98242", 0 },
{ "mcp98243", 0 },
{ "mcp9843", 0 },
{ "se97", 0 },
{ "se97b", 0 },
{ "se98", 0 },
{ "stts424", 0 },
{ "stts2002", 0 },
{ "stts3000", 0 },
{ "tse2002", 0 },
{ "ts3000", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, jc42_id);
@ -350,8 +332,10 @@ 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. */
/*
* 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)
@ -467,20 +451,19 @@ static const struct attribute_group jc42_group = {
};
/* Return 0 if detection is successful, -ENODEV otherwise */
static int jc42_detect(struct i2c_client *new_client,
struct i2c_board_info *info)
static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = new_client->adapter;
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(new_client, JC42_REG_CAP);
config = i2c_smbus_read_word_swapped(new_client, JC42_REG_CONFIG);
manid = i2c_smbus_read_word_swapped(new_client, JC42_REG_MANID);
devid = i2c_smbus_read_word_swapped(new_client, JC42_REG_DEVICEID);
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;
@ -499,47 +482,42 @@ static int jc42_detect(struct i2c_client *new_client,
return -ENODEV;
}
static int jc42_probe(struct i2c_client *new_client,
const struct i2c_device_id *id)
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 = kzalloc(sizeof(struct jc42_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(new_client, data);
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
cap = i2c_smbus_read_word_swapped(new_client, JC42_REG_CAP);
if (cap < 0) {
err = -EINVAL;
goto exit_free;
}
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(new_client, JC42_REG_CONFIG);
if (config < 0) {
err = -EINVAL;
goto exit_free;
}
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(new_client, JC42_REG_CONFIG,
config);
i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG, config);
}
data->config = config;
/* Register sysfs hooks */
err = sysfs_create_group(&new_client->dev.kobj, &jc42_group);
err = sysfs_create_group(&dev->kobj, &jc42_group);
if (err)
goto exit_free;
return err;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
data->hwmon_dev = hwmon_device_register(dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
goto exit_remove;
@ -548,10 +526,7 @@ static int jc42_probe(struct i2c_client *new_client,
return 0;
exit_remove:
sysfs_remove_group(&new_client->dev.kobj, &jc42_group);
exit_free:
kfree(data);
exit:
sysfs_remove_group(&dev->kobj, &jc42_group);
return err;
}
@ -563,7 +538,6 @@ static int jc42_remove(struct i2c_client *client)
if (data->config != data->orig_config)
i2c_smbus_write_word_swapped(client, JC42_REG_CONFIG,
data->orig_config);
kfree(data);
return 0;
}
@ -614,19 +588,8 @@ abort:
return ret;
}
static int __init sensors_jc42_init(void)
{
return i2c_add_driver(&jc42_driver);
}
static void __exit sensors_jc42_exit(void)
{
i2c_del_driver(&jc42_driver);
}
module_i2c_driver(jc42_driver);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_DESCRIPTION("JC42 driver");
MODULE_LICENSE("GPL");
module_init(sensors_jc42_init);
module_exit(sensors_jc42_exit);

View File

@ -205,7 +205,7 @@ static void __devexit k10temp_remove(struct pci_dev *pdev)
pci_set_drvdata(pdev, NULL);
}
static const struct pci_device_id k10temp_id_table[] = {
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) },

View File

@ -46,7 +46,7 @@ struct k8temp_data {
unsigned long last_updated; /* in jiffies */
/* registers values */
u8 sensorsp; /* sensor presence bits - SEL_CORE & SEL_PLACE */
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;
@ -63,7 +63,7 @@ static struct k8temp_data *k8temp_update_device(struct device *dev)
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 */
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]);
@ -82,7 +82,7 @@ static struct k8temp_data *k8temp_update_device(struct device *dev)
&data->temp[1][0]);
if (data->sensorsp & SEL_PLACE) {
tmp |= SEL_PLACE; /* Select sensor 1, core1 */
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]);
@ -136,7 +136,7 @@ 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 const struct pci_device_id k8temp_ids[] = {
static DEFINE_PCI_DEVICE_TABLE(k8temp_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
{ 0 },
};
@ -183,7 +183,8 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
u8 model, stepping;
struct k8temp_data *data;
if (!(data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL))) {
data = kzalloc(sizeof(struct k8temp_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
@ -217,7 +218,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
data->temp_offset = 21000;
pci_read_config_byte(pdev, REG_TEMP, &scfg);
scfg &= ~(SEL_PLACE | SEL_CORE); /* Select sensor 0, core0 */
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);
@ -238,7 +239,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
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 not likely */
if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is unlikely */
data->sensorsp &= ~SEL_PLACE;
}
@ -246,7 +247,7 @@ static int __devinit k8temp_probe(struct pci_dev *pdev,
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 not likely */
if (!((temp >> 16) & 0xff)) /* if temp is 0 -49C is unlikely */
data->sensorsp &= ~SEL_CORE;
}

View File

@ -448,7 +448,7 @@ static int pem_probe(struct i2c_client *client,
| I2C_FUNC_SMBUS_WRITE_BYTE))
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -462,11 +462,11 @@ static int pem_probe(struct i2c_client *client,
ret = pem_read_block(client, PEM_READ_FIRMWARE_REV,
data->firmware_rev, sizeof(data->firmware_rev));
if (ret < 0)
goto out_kfree;
return ret;
ret = i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);
if (ret < 0)
goto out_kfree;
return ret;
dev_info(&client->dev, "Firmware revision %d.%d.%d\n",
data->firmware_rev[0], data->firmware_rev[1],
@ -475,7 +475,7 @@ static int pem_probe(struct i2c_client *client,
/* Register sysfs hooks */
ret = sysfs_create_group(&client->dev.kobj, &pem_group);
if (ret)
goto out_kfree;
return ret;
/*
* Check if input readings are supported.
@ -534,8 +534,6 @@ 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);
out_kfree:
kfree(data);
return ret;
}
@ -549,7 +547,6 @@ static int pem_remove(struct i2c_client *client)
sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
sysfs_remove_group(&client->dev.kobj, &pem_group);
kfree(data);
return 0;
}
@ -568,19 +565,8 @@ static struct i2c_driver pem_driver = {
.id_table = pem_id,
};
static int __init pem_init(void)
{
return i2c_add_driver(&pem_driver);
}
static void __exit pem_exit(void)
{
i2c_del_driver(&pem_driver);
}
module_i2c_driver(pem_driver);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_DESCRIPTION("Lineage CPL PEM hardware monitoring driver");
MODULE_LICENSE("GPL");
module_init(pem_init);
module_exit(pem_exit);

View File

@ -1119,19 +1119,8 @@ static struct lm63_data *lm63_update_device(struct device *dev)
return data;
}
static int __init sensors_lm63_init(void)
{
return i2c_add_driver(&lm63_driver);
}
static void __exit sensors_lm63_exit(void)
{
i2c_del_driver(&lm63_driver);
}
module_i2c_driver(lm63_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("LM63 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm63_init);
module_exit(sensors_lm63_exit);

View File

@ -57,7 +57,7 @@ static ssize_t lm70_sense_temp(struct device *dev,
struct spi_device *spi = to_spi_device(dev);
int status, val = 0;
u8 rxbuf[2];
s16 raw=0;
s16 raw = 0;
struct lm70 *p_lm70 = spi_get_drvdata(spi);
if (mutex_lock_interruptible(&p_lm70->lock))
@ -156,6 +156,15 @@ static int __devinit lm70_probe(struct spi_device *spi)
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)) {
@ -163,20 +172,14 @@ static int __devinit lm70_probe(struct spi_device *spi)
status = PTR_ERR(p_lm70->hwmon_dev);
goto out_dev_reg_failed;
}
spi_set_drvdata(spi, p_lm70);
if ((status = device_create_file(&spi->dev, &dev_attr_temp1_input))
|| (status = device_create_file(&spi->dev, &dev_attr_name))) {
dev_dbg(&spi->dev, "device_create_file failure.\n");
goto out_dev_create_file_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);
hwmon_device_unregister(p_lm70->hwmon_dev);
out_dev_reg_failed:
out_dev_create_temp_file_failed:
spi_set_drvdata(spi, NULL);
kfree(p_lm70);
return status;
@ -186,9 +189,9 @@ 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);
hwmon_device_unregister(p_lm70->hwmon_dev);
spi_set_drvdata(spi, NULL);
kfree(p_lm70);
@ -213,18 +216,7 @@ static struct spi_driver lm70_driver = {
.remove = __devexit_p(lm70_remove),
};
static int __init init_lm70(void)
{
return spi_register_driver(&lm70_driver);
}
static void __exit cleanup_lm70(void)
{
spi_unregister_driver(&lm70_driver);
}
module_init(init_lm70);
module_exit(cleanup_lm70);
module_spi_driver(lm70_driver);
MODULE_AUTHOR("Kaiwan N Billimoria");
MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver");

View File

@ -194,21 +194,8 @@ static struct i2c_driver lm73_driver = {
.address_list = normal_i2c,
};
/* module glue */
static int __init sensors_lm73_init(void)
{
return i2c_add_driver(&lm73_driver);
}
static void __exit sensors_lm73_exit(void)
{
i2c_del_driver(&lm73_driver);
}
module_i2c_driver(lm73_driver);
MODULE_AUTHOR("Guillaume Ligneul <guillaume.ligneul@gmail.com>");
MODULE_DESCRIPTION("LM73 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm73_init);
module_exit(sensors_lm73_exit);

View File

@ -438,23 +438,8 @@ abort:
return ret;
}
/*-----------------------------------------------------------------------*/
/* module glue */
static int __init sensors_lm75_init(void)
{
return i2c_add_driver(&lm75_driver);
}
static void __exit sensors_lm75_exit(void)
{
i2c_del_driver(&lm75_driver);
}
module_i2c_driver(lm75_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
MODULE_DESCRIPTION("LM75 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm75_init);
module_exit(sensors_lm75_exit);

View File

@ -1,29 +1,29 @@
/*
lm77.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 2004 Andras BALI <drewie@freemail.hu>
Heavily based on lm75.c by Frodo Looijaard <frodol@dds.nl>. 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.
*/
* lm77.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
*
* Copyright (c) 2004 Andras BALI <drewie@freemail.hu>
*
* Heavily based on lm75.c by Frodo Looijaard <frodol@dds.nl>. 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 <linux/module.h>
#include <linux/init.h>
@ -49,7 +49,7 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
/* Each client has this additional data */
struct lm77_data {
struct device *hwmon_dev;
struct device *hwmon_dev;
struct mutex update_lock;
char valid;
unsigned long last_updated; /* In jiffies */
@ -95,8 +95,10 @@ static struct i2c_driver lm77_driver = {
#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. */
/*
* 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);
@ -112,7 +114,9 @@ static inline int LM77_TEMP_FROM_REG(s16 reg)
/* read routines for temperature limits */
#define show(value) \
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
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); \
@ -124,17 +128,20 @@ 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)
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)
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)
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);
@ -142,29 +149,42 @@ static ssize_t show_temp_max_hyst(struct device *dev, struct device_attribute *a
/* 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 = simple_strtol(buf, NULL, 10); \
\
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; \
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)
/*
* 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 = simple_strtoul(buf, NULL, 10);
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;
@ -175,13 +195,19 @@ static ssize_t set_temp_crit_hyst(struct device *dev, struct device_attribute *a
}
/* 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)
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);
long val = simple_strtoul(buf, NULL, 10);
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;
@ -251,17 +277,19 @@ static int lm77_detect(struct i2c_client *new_client,
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. */
/*
* 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);
@ -330,7 +358,8 @@ static int lm77_probe(struct i2c_client *new_client,
lm77_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm77_group)))
err = sysfs_create_group(&new_client->dev.kobj, &lm77_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
@ -358,8 +387,10 @@ static int lm77_remove(struct i2c_client *client)
return 0;
}
/* All registers are word-sized, except for the configuration register.
The LM77 uses the high-byte first convention. */
/*
* 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)
@ -420,19 +451,8 @@ static struct lm77_data *lm77_update_device(struct device *dev)
return data;
}
static int __init sensors_lm77_init(void)
{
return i2c_add_driver(&lm77_driver);
}
static void __exit sensors_lm77_exit(void)
{
i2c_del_driver(&lm77_driver);
}
module_i2c_driver(lm77_driver);
MODULE_AUTHOR("Andras BALI <drewie@freemail.hu>");
MODULE_DESCRIPTION("LM77 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm77_init);
module_exit(sensors_lm77_exit);

View File

@ -1,23 +1,23 @@
/*
lm78.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
Copyright (c) 2007, 2011 Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* lm78.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
* Copyright (c) 2007, 2011 Jean Delvare <khali@linux-fr.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@ -74,11 +74,15 @@ enum chips { lm78, lm79 };
#define LM78_REG_I2C_ADDR 0x48
/* Conversions. Rounding and limit checking is only done on the TO_REG
variants. */
/*
* Conversions. Rounding and limit checking is only done on the TO_REG
* variants.
*/
/* IN: mV, (0V to 4.08V)
REG: 16mV/bit */
/*
* 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);
@ -95,15 +99,17 @@ static inline u8 FAN_TO_REG(long rpm, int div)
static inline int FAN_FROM_REG(u8 val, int div)
{
return val==0 ? -1 : val==255 ? 0 : 1350000/(val*div);
return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div);
}
/* TEMP: mC (-128C to +127C)
REG: 1C/bit, two's complement */
/*
* 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;
return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000;
}
static inline int TEMP_FROM_REG(s8 val)
@ -177,8 +183,13 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct lm78_data *data = dev_get_drvdata(dev);
unsigned long val = simple_strtoul(buf, NULL, 10);
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);
@ -192,8 +203,13 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
{
struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct lm78_data *data = dev_get_drvdata(dev);
unsigned long val = simple_strtoul(buf, NULL, 10);
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);
@ -201,7 +217,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
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); \
@ -237,7 +253,12 @@ 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 = simple_strtol(buf, NULL, 10);
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);
@ -257,7 +278,12 @@ 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 = simple_strtol(buf, NULL, 10);
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);
@ -280,7 +306,7 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *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])) );
DIV_FROM_REG(data->fan_div[nr])));
}
static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
@ -289,8 +315,8 @@ static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
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])) );
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,
@ -299,7 +325,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
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 = simple_strtoul(buf, NULL, 10);
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]));
@ -316,29 +347,44 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
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. */
/*
* 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 val = simple_strtoul(buf, NULL, 10);
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;
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);
@ -484,8 +530,10 @@ 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. */
/*
* 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)
{
@ -515,8 +563,10 @@ static int lm78_alias_detect(struct i2c_client *client, u8 chipid)
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 */
/*
* 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))
@ -558,9 +608,11 @@ static int lm78_i2c_detect(struct i2c_client *client,
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. */
/*
* 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);
@ -669,11 +721,13 @@ static struct i2c_driver lm78_driver = {
.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. */
/*
* 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;
@ -691,13 +745,6 @@ static int lm78_read_value(struct lm78_data *data, u8 reg)
return i2c_smbus_read_byte_data(client, reg);
}
/* The SMBus locks itself, but ISA access muse 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.
There are some ugly typecasts here, but the good new is - they should
nowhere else be necessary! */
static int lm78_write_value(struct lm78_data *data, u8 reg, u8 value)
{
struct i2c_client *client = data->client;
@ -823,8 +870,11 @@ static int __devinit lm78_isa_probe(struct platform_device *pdev)
lm78_init_device(data);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&pdev->dev.kobj, &lm78_group))
|| (err = device_create_file(&pdev->dev, &dev_attr_name)))
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);
@ -876,9 +926,11 @@ 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
/*
* 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. */
* 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);
@ -887,8 +939,10 @@ static int __init lm78_isa_found(unsigned short address)
}
#define REALLY_SLOW_IO
/* We need the timeouts for at least some LM78-like
chips. But only if we read 'undefined' registers. */
/*
* 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
@ -896,8 +950,10 @@ static int __init lm78_isa_found(unsigned short address)
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. */
/*
* 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;
@ -1036,8 +1092,10 @@ 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. */
/*
* 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;

View File

@ -1,8 +1,8 @@
/*
* lm80.c - From lm_sensors, Linux kernel modules for hardware
* monitoring
* monitoring
* Copyright (C) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
* and Philip Edelbrock <phil@netroedge.com>
* and Philip Edelbrock <phil@netroedge.com>
*
* Ported to Linux 2.6 by Tiago Sousa <mirage@kaotik.org>
*
@ -60,11 +60,17 @@ static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
#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. */
/*
* 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)
@ -108,6 +114,7 @@ static inline long TEMP_FROM_REG(u16 temp)
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 */
@ -144,6 +151,7 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 value);
static const struct i2c_device_id lm80_id[] = {
{ "lm80", 0 },
{ "lm96080", 1 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm80_id);
@ -170,6 +178,8 @@ static ssize_t show_in_##suffix(struct device *dev, \
{ \
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)
@ -183,7 +193,10 @@ static ssize_t set_in_##suffix(struct device *dev, \
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 = simple_strtol(buf, NULL, 10); \
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); \
@ -200,6 +213,8 @@ static ssize_t show_fan_##suffix(struct device *dev, \
{ \
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]))); \
}
@ -211,6 +226,8 @@ static ssize_t show_fan_div(struct device *dev, struct device_attribute *attr,
{
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]));
}
@ -220,7 +237,10 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtoul(buf, NULL, 10);
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]));
@ -229,18 +249,23 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
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. */
/*
* 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 = simple_strtoul(buf, NULL, 10);
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);
@ -283,6 +308,8 @@ 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));
}
@ -291,6 +318,8 @@ 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);
@ -304,7 +333,10 @@ static ssize_t set_temp_##suffix(struct device *dev, \
{ \
struct i2c_client *client = to_i2c_client(dev); \
struct lm80_data *data = i2c_get_clientdata(client); \
long val = simple_strtoul(buf, NULL, 10); \
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); \
@ -321,6 +353,8 @@ 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);
}
@ -329,6 +363,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
{
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);
}
@ -459,23 +495,44 @@ static const struct attribute_group lm80_group = {
static int lm80_detect(struct i2c_client *client, struct i2c_board_info *info)
{
struct i2c_adapter *adapter = client->adapter;
int i, cur;
int i, cur, man_id, dev_id;
const char *name = NULL;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV;
/* Now, we do the remaining detection. It is lousy. */
if (lm80_read_value(client, LM80_REG_ALARM2) & 0xc0)
/* 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;
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))
/*
* 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, "lm80", I2C_NAME_SIZE);
strlcpy(info->type, name, I2C_NAME_SIZE);
return 0;
}
@ -547,9 +604,11 @@ static int lm80_write_value(struct i2c_client *client, u8 reg, u8 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 */
/*
* 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);
@ -563,66 +622,116 @@ 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++) {
data->in[i] =
lm80_read_value(client, LM80_REG_IN(i));
data->in_min[i] =
lm80_read_value(client, LM80_REG_IN_MIN(i));
data->in_max[i] =
lm80_read_value(client, LM80_REG_IN_MAX(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;
}
data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
data->fan_min[0] =
lm80_read_value(client, LM80_REG_FAN_MIN(1));
data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
data->fan_min[1] =
lm80_read_value(client, LM80_REG_FAN_MIN(2));
data->temp =
(lm80_read_value(client, LM80_REG_TEMP) << 8) |
(lm80_read_value(client, LM80_REG_RES) & 0xf0);
data->temp_os_max =
lm80_read_value(client, LM80_REG_TEMP_OS_MAX);
data->temp_os_hyst =
lm80_read_value(client, LM80_REG_TEMP_OS_HYST);
data->temp_hot_max =
lm80_read_value(client, LM80_REG_TEMP_HOT_MAX);
data->temp_hot_hyst =
lm80_read_value(client, LM80_REG_TEMP_HOT_HYST);
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);
i = lm80_read_value(client, LM80_REG_FANDIV);
data->fan_div[0] = (i >> 2) & 0x03;
data->fan_div[1] = (i >> 4) & 0x03;
data->alarms = lm80_read_value(client, LM80_REG_ALARM1) +
(lm80_read_value(client, LM80_REG_ALARM2) << 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 data;
return ret;
}
static int __init sensors_lm80_init(void)
{
return i2c_add_driver(&lm80_driver);
}
static void __exit sensors_lm80_exit(void)
{
i2c_del_driver(&lm80_driver);
}
module_i2c_driver(lm80_driver);
MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
"Philip Edelbrock <phil@netroedge.com>");
MODULE_DESCRIPTION("LM80 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm80_init);
module_exit(sensors_lm80_exit);

View File

@ -124,7 +124,7 @@ 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 },
@ -179,8 +179,13 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -355,12 +360,14 @@ static int lm83_probe(struct i2c_client *new_client,
* declare 1 and 3 common, and then 2 and 4 only for the LM83.
*/
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm83_group)))
err = sysfs_create_group(&new_client->dev.kobj, &lm83_group);
if (err)
goto exit_free;
if (id->driver_data == lm83) {
if ((err = sysfs_create_group(&new_client->dev.kobj,
&lm83_group_opt)))
err = sysfs_create_group(&new_client->dev.kobj,
&lm83_group_opt);
if (err)
goto exit_remove_files;
}
@ -423,19 +430,8 @@ static struct lm83_data *lm83_update_device(struct device *dev)
return data;
}
static int __init sensors_lm83_init(void)
{
return i2c_add_driver(&lm83_driver);
}
static void __exit sensors_lm83_exit(void)
{
i2c_del_driver(&lm83_driver);
}
module_i2c_driver(lm83_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("LM83 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm83_init);
module_exit(sensors_lm83_exit);

View File

@ -1,28 +1,28 @@
/*
lm85.c - Part of lm_sensors, Linux kernel modules for hardware
monitoring
Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
Copyright (C) 2007--2009 Jean Delvare <khali@linux-fr.org>
Chip details at <http://www.national.com/ds/LM/LM85.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.
*/
* lm85.c - Part of lm_sensors, Linux kernel modules for hardware
* monitoring
* Copyright (c) 1998, 1999 Frodo Looijaard <frodol@dds.nl>
* Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
* Copyright (c) 2003 Margit Schubert-While <margitsw@t-online.de>
* Copyright (c) 2004 Justin Thiessen <jthiessen@penguincomputing.com>
* Copyright (C) 2007--2009 Jean Delvare <khali@linux-fr.org>
*
* Chip details at <http://www.national.com/ds/LM/LM85.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 <linux/module.h>
#include <linux/init.h>
@ -46,88 +46,89 @@ enum chips {
/* 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_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)
#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_FAN(nr) (0x28 + (nr) * 2)
#define LM85_REG_FAN_MIN(nr) (0x54 + (nr) * 2)
#define LM85_REG_PWM(nr) (0x30 + (nr))
#define LM85_REG_PWM(nr) (0x30 + (nr))
#define LM85_REG_COMPANY 0x3e
#define LM85_REG_VERSTEP 0x3f
#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) \
#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) \
#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_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_CONFIG 0x40
#define LM85_REG_ALARM1 0x41
#define LM85_REG_ALARM2 0x42
#define LM85_REG_ALARM1 0x41
#define LM85_REG_ALARM2 0x42
#define LM85_REG_VID 0x43
#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 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 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
#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.
/*
* 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 */
@ -166,7 +167,8 @@ static inline u16 FAN_TO_REG(unsigned long val)
#define PWM_FROM_REG(val) (val)
/* ZONEs have the following parameters:
/*
* 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)
@ -228,7 +230,8 @@ 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
/*
* 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
@ -258,7 +261,8 @@ static int ZONE_TO_REG(int zone)
#define HYST_TO_REG(val) SENSORS_LIMIT(((val) + 500) / 1000, 0, 15)
#define HYST_FROM_REG(val) ((val) * 1000)
/* Chip sampling rates
/*
* 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.
@ -274,7 +278,8 @@ static int ZONE_TO_REG(int zone)
#define LM85_DATA_INTERVAL (HZ + HZ / 2)
#define LM85_CONFIG_INTERVAL (1 * 60 * HZ)
/* LM85 can automatically adjust fan speeds based on temperature
/*
* 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
*/
@ -283,7 +288,8 @@ struct lm85_zone {
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
u8 max_desired; /*
* Actual "max" temperature specified. Preserved
* to prevent "drift" as other autofan control
* values change.
*/
@ -295,8 +301,10 @@ struct lm85_autofan {
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. */
/*
* 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;
@ -391,7 +399,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtoul(buf, NULL, 10);
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);
@ -443,7 +456,14 @@ 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);
data->vrm = simple_strtoul(buf, NULL, 10);
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
data->vrm = val;
return count;
}
@ -500,7 +520,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -537,8 +562,13 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
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 = simple_strtol(buf, NULL, 10);
u8 config;
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
switch (val) {
case 0:
@ -548,8 +578,10 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
config = 7;
break;
case 2:
/* Here we have to choose arbitrarily one of the 5 possible
configurations; I go for the safest */
/*
* Here we have to choose arbitrarily one of the 5 possible
* configurations; I go for the safest
*/
config = 6;
break;
default:
@ -588,12 +620,19 @@ static ssize_t set_pwm_freq(struct device *dev,
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 = simple_strtol(buf, NULL, 10);
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,
/*
* 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. */
* 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);
@ -648,7 +687,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -671,7 +715,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
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);
@ -722,7 +771,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
long val;
int err;
err = kstrtol(buf, 10, &val);
if (err)
return err;
if (IS_ADT7468_OFF64(data))
val += 64;
@ -748,7 +802,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
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 = simple_strtol(buf, NULL, 10);
long val;
int err;
err = kstrtol(buf, 10, &val);
if (err)
return err;
if (IS_ADT7468_OFF64(data))
val += 64;
@ -789,7 +848,12 @@ static ssize_t set_pwm_auto_channels(struct device *dev,
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 = simple_strtol(buf, NULL, 10);
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))
@ -814,7 +878,12 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev,
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 = simple_strtol(buf, NULL, 10);
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);
@ -838,8 +907,13 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev,
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 = simple_strtol(buf, NULL, 10);
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;
@ -885,7 +959,12 @@ static ssize_t set_temp_auto_temp_off(struct device *dev,
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
int min;
long val = simple_strtol(buf, NULL, 10);
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);
@ -916,7 +995,12 @@ static ssize_t set_temp_auto_temp_min(struct device *dev,
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 = simple_strtol(buf, NULL, 10);
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);
@ -951,7 +1035,12 @@ static ssize_t set_temp_auto_temp_max(struct device *dev,
struct i2c_client *client = to_i2c_client(dev);
struct lm85_data *data = i2c_get_clientdata(client);
int min;
long val = simple_strtol(buf, NULL, 10);
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);
@ -979,7 +1068,12 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev,
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 = simple_strtol(buf, NULL, 10);
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);
@ -1338,24 +1432,28 @@ static int lm85_probe(struct i2c_client *client,
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. */
/*
* 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)
if ((err = sysfs_create_group(&client->dev.kobj,
&lm85_group_in4)))
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)
if ((err = sysfs_create_group(&client->dev.kobj,
&lm85_group_in567)))
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)) {
@ -1443,7 +1541,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
/* Things that change quickly */
dev_dbg(&client->dev, "Reading sensor values\n");
/* Have to read extended bits first to "freeze" the
/*
* 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.
@ -1503,9 +1602,10 @@ static struct lm85_data *lm85_update_device(struct device *dev)
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).
/*
* 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);
@ -1611,22 +1711,10 @@ static struct lm85_data *lm85_update_device(struct device *dev)
return data;
}
static int __init sm_lm85_init(void)
{
return i2c_add_driver(&lm85_driver);
}
static void __exit sm_lm85_exit(void)
{
i2c_del_driver(&lm85_driver);
}
module_i2c_driver(lm85_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Philip Pokorny <ppokorny@penguincomputing.com>, "
"Margit Schubert-While <margitsw@t-online.de>, "
"Justin Thiessen <jthiessen@penguincomputing.com>");
MODULE_DESCRIPTION("LM85-B, LM85-C driver");
module_init(sm_lm85_init);
module_exit(sm_lm85_exit);

File diff suppressed because it is too large Load Diff

View File

@ -1514,19 +1514,8 @@ static struct i2c_driver lm90_driver = {
.address_list = normal_i2c,
};
static int __init sensors_lm90_init(void)
{
return i2c_add_driver(&lm90_driver);
}
static void __exit sensors_lm90_exit(void)
{
i2c_del_driver(&lm90_driver);
}
module_i2c_driver(lm90_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("LM90/ADM1032 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm90_init);
module_exit(sensors_lm90_exit);

View File

@ -49,8 +49,10 @@
#include <linux/err.h>
#include <linux/mutex.h>
/* The LM92 and MAX6635 have 2 two-state pins for address selection,
resulting in 4 possible addresses. */
/*
* 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 };
@ -63,11 +65,13 @@ static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b,
#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). */
/*
* 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;
@ -138,7 +142,8 @@ static struct lm92_data *lm92_update_device(struct device *dev)
}
#define show_temp(value) \
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
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)); \
@ -149,13 +154,17 @@ 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, \
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 = simple_strtol(buf, NULL, 10); \
\
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); \
@ -166,31 +175,40 @@ 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)
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)
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)
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)
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 = simple_strtol(buf, NULL, 10);
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;
@ -200,7 +218,8 @@ static ssize_t set_temp1_crit_hyst(struct device *dev, struct device_attribute *
return count;
}
static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
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));
@ -246,26 +265,30 @@ static void lm92_init_client(struct i2c_client *client)
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. */
/*
* 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. */
/*
* 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;
@ -274,22 +297,24 @@ static int max6635_check(struct i2c_client *client)
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. */
/*
* 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) {
for (i = 16; i < 96; i *= 2) {
if (temp_hyst != i2c_smbus_read_word_data(client,
LM92_REG_TEMP_HYST + i - 16)
LM92_REG_TEMP_HYST + i - 16)
|| temp_crit != i2c_smbus_read_word_data(client,
LM92_REG_TEMP_CRIT + i)
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)
LM92_REG_TEMP_HIGH + i + 32)
|| conf != i2c_smbus_read_byte_data(client,
LM92_REG_CONFIG + i))
LM92_REG_CONFIG + i))
return 0;
}
@ -362,7 +387,8 @@ static int lm92_probe(struct i2c_client *new_client,
lm92_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &lm92_group)))
err = sysfs_create_group(&new_client->dev.kobj, &lm92_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
@ -416,19 +442,8 @@ static struct i2c_driver lm92_driver = {
.address_list = normal_i2c,
};
static int __init sensors_lm92_init(void)
{
return i2c_add_driver(&lm92_driver);
}
static void __exit sensors_lm92_exit(void)
{
i2c_del_driver(&lm92_driver);
}
module_i2c_driver(lm92_driver);
MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("LM92/MAX6635 driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm92_init);
module_exit(sensors_lm92_exit);

File diff suppressed because it is too large Load Diff

View File

@ -455,19 +455,8 @@ static struct i2c_driver lm95241_driver = {
.address_list = normal_i2c,
};
static int __init sensors_lm95241_init(void)
{
return i2c_add_driver(&lm95241_driver);
}
static void __exit sensors_lm95241_exit(void)
{
i2c_del_driver(&lm95241_driver);
}
module_i2c_driver(lm95241_driver);
MODULE_AUTHOR("Davide Rizzo <elpa.rizzo@gmail.com>");
MODULE_DESCRIPTION("LM95241 sensor driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm95241_init);
module_exit(sensors_lm95241_exit);

View File

@ -525,19 +525,8 @@ static struct i2c_driver lm95245_driver = {
.address_list = normal_i2c,
};
static int __init sensors_lm95245_init(void)
{
return i2c_add_driver(&lm95245_driver);
}
static void __exit sensors_lm95245_exit(void)
{
i2c_del_driver(&lm95245_driver);
}
module_i2c_driver(lm95245_driver);
MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>");
MODULE_DESCRIPTION("LM95245 sensor driver");
MODULE_LICENSE("GPL");
module_init(sensors_lm95245_init);
module_exit(sensors_lm95245_exit);

View File

@ -154,7 +154,8 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, \
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,
/*
* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
static struct attribute *ltc4151_attributes[] = {
@ -238,19 +239,8 @@ static struct i2c_driver ltc4151_driver = {
.id_table = ltc4151_id,
};
static int __init ltc4151_init(void)
{
return i2c_add_driver(&ltc4151_driver);
}
static void __exit ltc4151_exit(void)
{
i2c_del_driver(&ltc4151_driver);
}
module_i2c_driver(ltc4151_driver);
MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
MODULE_DESCRIPTION("LTC4151 driver");
MODULE_LICENSE("GPL");
module_init(ltc4151_init);
module_exit(ltc4151_exit);

View File

@ -91,8 +91,10 @@ static int ltc4215_get_voltage(struct device *dev, u8 reg)
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 */
/*
* 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:
@ -109,7 +111,8 @@ 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
/*
* 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
@ -176,7 +179,8 @@ static ssize_t ltc4215_show_alarm(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%u\n", (reg & mask) ? 1 : 0);
}
/* These macros are used below in constructing device attribute objects
/*
* 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.
*/
@ -215,7 +219,8 @@ LTC4215_ALARM(in1_min_alarm, (1 << 1), LTC4215_STATUS);
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,
/*
* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
static struct attribute *ltc4215_attributes[] = {
@ -309,19 +314,8 @@ static struct i2c_driver ltc4215_driver = {
.id_table = ltc4215_id,
};
static int __init ltc4215_init(void)
{
return i2c_add_driver(&ltc4215_driver);
}
static void __exit ltc4215_exit(void)
{
i2c_del_driver(&ltc4215_driver);
}
module_i2c_driver(ltc4215_driver);
MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
MODULE_DESCRIPTION("LTC4215 driver");
MODULE_LICENSE("GPL");
module_init(ltc4215_init);
module_exit(ltc4215_exit);

View File

@ -214,7 +214,8 @@ static unsigned int ltc4245_get_current(struct device *dev, u8 reg)
unsigned int voltage;
unsigned int curr;
/* The strange looking conversions that follow are fixed-point
/*
* 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
@ -317,7 +318,8 @@ static ssize_t ltc4245_show_gpio(struct device *dev,
return snprintf(buf, PAGE_SIZE, "%u\n", val * 10);
}
/* These macros are used below in constructing device attribute objects
/*
* 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.
*/
@ -391,7 +393,8 @@ 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,
/*
* Finally, construct an array of pointers to members of the above objects,
* as required for sysfs_create_group()
*/
static struct attribute *ltc4245_std_attributes[] = {
@ -578,19 +581,8 @@ static struct i2c_driver ltc4245_driver = {
.id_table = ltc4245_id,
};
static int __init ltc4245_init(void)
{
return i2c_add_driver(&ltc4245_driver);
}
static void __exit ltc4245_exit(void)
{
i2c_del_driver(&ltc4245_driver);
}
module_i2c_driver(ltc4245_driver);
MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
MODULE_DESCRIPTION("LTC4245 driver");
MODULE_LICENSE("GPL");
module_init(ltc4245_init);
module_exit(ltc4245_exit);

View File

@ -235,11 +235,9 @@ static int ltc4261_probe(struct i2c_client *client,
return -ENODEV;
}
data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) {
ret = -ENOMEM;
goto out_kzalloc;
}
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data)
return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock);
@ -250,7 +248,7 @@ static int ltc4261_probe(struct i2c_client *client,
/* Register sysfs hooks */
ret = sysfs_create_group(&client->dev.kobj, &ltc4261_group);
if (ret)
goto out_sysfs_create_group;
return ret;
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@ -262,9 +260,6 @@ static int ltc4261_probe(struct i2c_client *client,
out_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
out_sysfs_create_group:
kfree(data);
out_kzalloc:
return ret;
}
@ -275,8 +270,6 @@ static int ltc4261_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &ltc4261_group);
kfree(data);
return 0;
}
@ -297,19 +290,8 @@ static struct i2c_driver ltc4261_driver = {
.id_table = ltc4261_id,
};
static int __init ltc4261_init(void)
{
return i2c_add_driver(&ltc4261_driver);
}
static void __exit ltc4261_exit(void)
{
i2c_del_driver(&ltc4261_driver);
}
module_i2c_driver(ltc4261_driver);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_DESCRIPTION("LTC4261 driver");
MODULE_LICENSE("GPL");
module_init(ltc4261_init);
module_exit(ltc4261_exit);

View File

@ -106,7 +106,8 @@ static ssize_t show_adc(struct device *dev,
if (ret < 0)
return ret;
/* assume the reference voltage to be 2.048V, with an 8-bit sample,
/*
* 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);
@ -227,17 +228,7 @@ static struct spi_driver max1111_driver = {
.remove = __devexit_p(max1111_remove),
};
static int __init max1111_init(void)
{
return spi_register_driver(&max1111_driver);
}
module_init(max1111_init);
static void __exit max1111_exit(void)
{
spi_unregister_driver(&max1111_driver);
}
module_exit(max1111_exit);
module_spi_driver(max1111_driver);
MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>");
MODULE_DESCRIPTION("MAX1111 ADC Driver");

View File

@ -554,7 +554,7 @@ static int max16065_probe(struct i2c_client *client,
| I2C_FUNC_SMBUS_READ_WORD_DATA))
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (unlikely(!data))
return -ENOMEM;
@ -567,20 +567,16 @@ static int max16065_probe(struct i2c_client *client,
if (have_secondary) {
val = i2c_smbus_read_byte_data(client, MAX16065_SW_ENABLE);
if (unlikely(val < 0)) {
ret = val;
goto out_free;
}
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)) {
ret = val;
goto out_free;
}
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];
@ -595,10 +591,8 @@ static int max16065_probe(struct i2c_client *client,
for (j = 0; j < data->num_adc; j++) {
val = i2c_smbus_read_byte_data(client,
MAX16065_LIMIT(i, j));
if (unlikely(val < 0)) {
ret = val;
goto out_free;
}
if (unlikely(val < 0))
return val;
data->limit[i][j] = LIMIT_TO_MV(val, data->range[j]);
}
}
@ -661,8 +655,6 @@ static int max16065_probe(struct i2c_client *client,
out:
max16065_cleanup(client);
out_free:
kfree(data);
return ret;
}
@ -672,7 +664,6 @@ static int max16065_remove(struct i2c_client *client)
hwmon_device_unregister(data->hwmon_dev);
max16065_cleanup(client);
kfree(data);
return 0;
}
@ -699,19 +690,8 @@ static struct i2c_driver max16065_driver = {
.id_table = max16065_id,
};
static int __init max16065_init(void)
{
return i2c_add_driver(&max16065_driver);
}
static void __exit max16065_exit(void)
{
i2c_del_driver(&max16065_driver);
}
module_i2c_driver(max16065_driver);
MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
MODULE_DESCRIPTION("MAX16065 driver");
MODULE_LICENSE("GPL");
module_init(max16065_init);
module_exit(max16065_exit);

View File

@ -125,7 +125,7 @@ struct max1619_data {
u8 temp_input2, temp_low2, temp_high2; /* remote */
u8 temp_crit2;
u8 temp_hyst2;
u8 alarms;
u8 alarms;
};
/*
@ -133,7 +133,8 @@ struct max1619_data {
*/
#define show_temp(value) \
static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \
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)); \
@ -146,13 +147,17 @@ 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, \
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 = simple_strtol(buf, NULL, 10); \
\
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); \
@ -165,7 +170,8 @@ 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)
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);
@ -275,7 +281,8 @@ static int max1619_probe(struct i2c_client *new_client,
max1619_init_client(new_client);
/* Register sysfs hooks */
if ((err = sysfs_create_group(&new_client->dev.kobj, &max1619_group)))
err = sysfs_create_group(&new_client->dev.kobj, &max1619_group);
if (err)
goto exit_free;
data->hwmon_dev = hwmon_device_register(&new_client->dev);
@ -353,20 +360,9 @@ static struct max1619_data *max1619_update_device(struct device *dev)
return data;
}
static int __init sensors_max1619_init(void)
{
return i2c_add_driver(&max1619_driver);
}
static void __exit sensors_max1619_exit(void)
{
i2c_del_driver(&max1619_driver);
}
module_i2c_driver(max1619_driver);
MODULE_AUTHOR("Alexey Fisher <fishor@mail.ru> and "
"Jean Delvare <khali@linux-fr.org>");
MODULE_DESCRIPTION("MAX1619 sensor driver");
MODULE_LICENSE("GPL");
module_init(sensors_max1619_init);
module_exit(sensors_max1619_exit);

View File

@ -1,23 +1,23 @@
/*
Copyright (c) 2011 David George <david.george@ska.ac.za>
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.
*/
* Copyright (c) 2011 David George <david.george@ska.ac.za>
*
* 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 <linux/module.h>
#include <linux/init.h>
@ -484,19 +484,8 @@ static struct i2c_driver max1668_driver = {
.address_list = max1668_addr_list,
};
static int __init sensors_max1668_init(void)
{
return i2c_add_driver(&max1668_driver);
}
static void __exit sensors_max1668_exit(void)
{
i2c_del_driver(&max1668_driver);
}
module_i2c_driver(max1668_driver);
MODULE_AUTHOR("David George <david.george@ska.ac.za>");
MODULE_DESCRIPTION("MAX1668 remote temperature sensor driver");
MODULE_LICENSE("GPL");
module_init(sensors_max1668_init)
module_exit(sensors_max1668_exit)

View File

@ -637,19 +637,8 @@ static struct i2c_driver max6639_driver = {
.address_list = normal_i2c,
};
static int __init max6639_init(void)
{
return i2c_add_driver(&max6639_driver);
}
static void __exit max6639_exit(void)
{
i2c_del_driver(&max6639_driver);
}
module_i2c_driver(max6639_driver);
MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
MODULE_DESCRIPTION("max6639 driver");
MODULE_LICENSE("GPL");
module_init(max6639_init);
module_exit(max6639_exit);

View File

@ -352,19 +352,8 @@ static struct i2c_driver max6642_driver = {
.address_list = normal_i2c,
};
static int __init max6642_init(void)
{
return i2c_add_driver(&max6642_driver);
}
static void __exit max6642_exit(void)
{
i2c_del_driver(&max6642_driver);
}
module_i2c_driver(max6642_driver);
MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
MODULE_DESCRIPTION("MAX6642 sensor driver");
MODULE_LICENSE("GPL");
module_init(max6642_init);
module_exit(max6642_exit);

View File

@ -135,8 +135,7 @@ static struct i2c_driver max6650_driver = {
* Client data (each client gets its own)
*/
struct max6650_data
{
struct max6650_data {
struct device *hwmon_dev;
struct mutex update_lock;
int nr_fans;
@ -160,13 +159,13 @@ static ssize_t get_fan(struct device *dev, struct device_attribute *devattr,
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).
*/
* 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);
@ -220,12 +219,12 @@ static ssize_t get_target(struct device *dev, struct device_attribute *devattr,
int kscale, ktach, rpm;
/*
* Use the datasheet equation:
*
* FanSpeed = KSCALE x fCLK / [256 x (KTACH + 1)]
*
* then multiply by 60 to give 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;
@ -238,17 +237,22 @@ static ssize_t set_target(struct device *dev, struct device_attribute *devattr,
{
struct i2c_client *client = to_i2c_client(dev);
struct max6650_data *data = i2c_get_clientdata(client);
int rpm = simple_strtoul(buf, NULL, 10);
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
*/
* 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);
@ -282,8 +286,10 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *devattr,
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. */
/*
* 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
@ -300,7 +306,12 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr,
{
struct i2c_client *client = to_i2c_client(dev);
struct max6650_data *data = i2c_get_clientdata(client);
int pwm = simple_strtoul(buf, NULL, 10);
unsigned long pwm;
int err;
err = kstrtoul(buf, 10, &pwm);
if (err)
return err;
pwm = SENSORS_LIMIT(pwm, 0, 255);
@ -341,14 +352,16 @@ static ssize_t set_enable(struct device *dev, struct device_attribute *devattr,
{
struct i2c_client *client = to_i2c_client(dev);
struct max6650_data *data = i2c_get_clientdata(client);
int mode = simple_strtoul(buf, NULL, 10);
int max6650_modes[3] = {0, 3, 2};
unsigned long mode;
int err;
if ((mode < 0)||(mode > 2)) {
dev_err(&client->dev,
"illegal value for pwm1_enable (%d)\n", mode);
err = kstrtoul(buf, 10, &mode);
if (err)
return err;
if (mode > 2)
return -EINVAL;
}
mutex_lock(&data->update_lock);
@ -389,7 +402,12 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
{
struct i2c_client *client = to_i2c_client(dev);
struct max6650_data *data = i2c_get_clientdata(client);
int div = simple_strtoul(buf, NULL, 10);
unsigned long div;
int err;
err = kstrtoul(buf, 10, &div);
if (err)
return err;
mutex_lock(&data->update_lock);
switch (div) {
@ -407,8 +425,6 @@ static ssize_t set_div(struct device *dev, struct device_attribute *devattr,
break;
default:
mutex_unlock(&data->update_lock);
dev_err(&client->dev,
"illegal value for fan divider (%d)\n", div);
return -EINVAL;
}
@ -529,7 +545,8 @@ static int max6650_probe(struct i2c_client *client,
struct max6650_data *data;
int err;
if (!(data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL))) {
data = kzalloc(sizeof(struct max6650_data), GFP_KERNEL);
if (!data) {
dev_err(&client->dev, "out of memory.\n");
return -ENOMEM;
}
@ -596,55 +613,54 @@ static int max6650_init_client(struct i2c_client *client)
}
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);
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);
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
/*
* 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.
*/
@ -698,9 +714,11 @@ static struct max6650_data *max6650_update_device(struct device *dev)
MAX6650_REG_COUNT);
data->dac = i2c_smbus_read_byte_data(client, MAX6650_REG_DAC);
/* Alarms are cleared on read in case the condition that
/*
* 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. */
* for providing the register through different alarm files.
*/
data->alarm |= i2c_smbus_read_byte_data(client,
MAX6650_REG_ALARM);
@ -713,19 +731,8 @@ static struct max6650_data *max6650_update_device(struct device *dev)
return data;
}
static int __init sensors_max6650_init(void)
{
return i2c_add_driver(&max6650_driver);
}
static void __exit sensors_max6650_exit(void)
{
i2c_del_driver(&max6650_driver);
}
module_i2c_driver(max6650_driver);
MODULE_AUTHOR("Hans J. Koch");
MODULE_DESCRIPTION("MAX6650 sensor driver");
MODULE_LICENSE("GPL");
module_init(sensors_max6650_init);
module_exit(sensors_max6650_exit);

File diff suppressed because it is too large Load Diff

View File

@ -46,9 +46,11 @@ 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). */
/*
* 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;
@ -173,10 +175,12 @@ static inline void pc87427_write8_bank(struct pc87427_data *data, u8 ldi,
#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 */
/*
* 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];
@ -189,8 +193,10 @@ static void pc87427_readall_fan(struct pc87427_data *data, u8 nr)
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. */
/*
* 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;
@ -224,10 +230,12 @@ static inline u16 fan_to_reg(unsigned long val)
#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 */
/*
* 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];
@ -286,10 +294,12 @@ static inline u8 pwm_enable_to_reg(unsigned long val, u8 pwmval)
#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 */
/*
* 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];
@ -318,8 +328,10 @@ static inline unsigned int temp_type_from_reg(u8 reg)
}
}
/* 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. */
/*
* 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;
@ -423,9 +435,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute
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. */
/*
* 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);
@ -542,8 +556,10 @@ static const struct attribute_group pc87427_group_fan[8] = {
{ .attrs = pc87427_attributes_fan[7] },
};
/* Must be called with data->lock held and pc87427_readall_pwm() freshly
called */
/*
* 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];
@ -1023,9 +1039,11 @@ static void __devinit pc87427_init_device(struct device *dev)
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. */
/*
* 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);

View File

@ -1,22 +1,22 @@
/*
Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
the help of Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
* Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
* Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
* the help of Jean Delvare <khali@linux-fr.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@ -39,28 +39,34 @@ MODULE_PARM_DESC(input_mode,
" 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 | */
/*
* 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 */
/*
* 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 */
/*
* Channel selection
* 0x00 = channel 0
* 0x01 = channel 1
* 0x02 = channel 2
* 0x03 = channel 3
*/
#define PCF8591_CONTROL_AICH_MASK 0x03
/* Initial values */
@ -68,7 +74,7 @@ MODULE_PARM_DESC(input_mode,
#define PCF8591_INIT_AOUT 0 /* DAC out = 0 */
/* Conversions */
#define REG_TO_SIGNED(reg) (((reg) & 0x80)?((reg) - 256):(reg))
#define REG_TO_SIGNED(reg) (((reg) & 0x80) ? ((reg) - 256) : (reg))
struct pcf8591_data {
struct device *hwmon_dev;
@ -83,7 +89,9 @@ 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) \
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));\
} \
@ -95,39 +103,57 @@ 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)
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)
static ssize_t set_out0_output(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
unsigned int value;
unsigned long val;
struct i2c_client *client = to_i2c_client(dev);
struct pcf8591_data *data = i2c_get_clientdata(client);
if ((value = (simple_strtoul(buf, NULL, 10) + 5) / 10) <= 255) {
data->aout = value;
i2c_smbus_write_byte_data(client, data->control, data->aout);
return count;
}
return -EINVAL;
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)
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)
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 = simple_strtoul(buf, NULL, 10);
unsigned long val;
int err;
err = kstrtoul(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
if (val)
@ -174,7 +200,8 @@ static int pcf8591_probe(struct i2c_client *client,
struct pcf8591_data *data;
int err;
if (!(data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
data = kzalloc(sizeof(struct pcf8591_data), GFP_KERNEL);
if (!data) {
err = -ENOMEM;
goto exit;
}
@ -192,15 +219,15 @@ static int pcf8591_probe(struct i2c_client *client,
/* Register input2 if not in "two differential inputs" mode */
if (input_mode != 3) {
if ((err = device_create_file(&client->dev,
&dev_attr_in2_input)))
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) {
if ((err = device_create_file(&client->dev,
&dev_attr_in3_input)))
err = device_create_file(&client->dev, &dev_attr_in3_input);
if (err)
goto exit_sysfs_remove;
}
@ -241,8 +268,10 @@ static void pcf8591_init_client(struct i2c_client *client)
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! */
/*
* The first byte transmitted contains the conversion code of the
* previous read cycle. FLUSH IT!
*/
i2c_smbus_read_byte(client);
}
@ -259,8 +288,10 @@ static int pcf8591_read_channel(struct device *dev, int channel)
| channel;
i2c_smbus_write_byte(client, data->control);
/* The first byte transmitted contains the conversion code of
the previous read cycle. FLUSH IT! */
/*
* 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);
@ -269,9 +300,9 @@ static int pcf8591_read_channel(struct device *dev, int channel)
if ((channel == 2 && input_mode == 2) ||
(channel != 3 && (input_mode == 1 || input_mode == 3)))
return (10 * REG_TO_SIGNED(value));
return 10 * REG_TO_SIGNED(value);
else
return (10 * value);
return 10 * value;
}
static const struct i2c_device_id pcf8591_id[] = {

View File

@ -20,7 +20,8 @@ config SENSORS_PMBUS
help
If you say yes here you get hardware monitoring support for generic
PMBus devices, including but not limited to ADP4000, BMR453, BMR454,
NCP4200, and NCP4208.
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.
@ -30,8 +31,8 @@ config SENSORS_ADM1275
default n
help
If you say yes here you get hardware monitoring support for Analog
Devices ADM1275 and ADM1276 Hot-Swap Controller and Digital Power
Monitor.
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.
@ -67,11 +68,11 @@ config SENSORS_MAX16064
be called max16064.
config SENSORS_MAX34440
tristate "Maxim MAX34440/MAX34441"
tristate "Maxim MAX34440 and compatibles"
default n
help
If you say yes here you get hardware monitoring support for Maxim
MAX34440 and MAX34441.
MAX34440, MAX34441, and MAX34446.
This driver can also be built as a module. If so, the module will
be called max34440.
@ -113,9 +114,9 @@ config SENSORS_ZL6100
default n
help
If you say yes here you get hardware monitoring support for Intersil
ZL2004, ZL2005, ZL2006, ZL2008, ZL2105, ZL2106, ZL6100, and ZL6105
Digital DC/DC Controllers, as well as for Ericsson BMR450, BMR451,
BMR462, BMR463, and BMR464.
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.

View File

@ -23,7 +23,7 @@
#include <linux/i2c.h>
#include "pmbus.h"
enum chips { adm1275, adm1276 };
enum chips { adm1075, adm1275, adm1276 };
#define ADM1275_PEAK_IOUT 0xd0
#define ADM1275_PEAK_VIN 0xd1
@ -32,6 +32,9 @@ enum chips { adm1275, adm1276 };
#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
@ -42,6 +45,14 @@ enum chips { adm1275, adm1276 };
#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;
@ -74,6 +85,29 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
}
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;
@ -84,7 +118,7 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
ret = pmbus_read_word_data(client, 0, ADM1275_PEAK_VIN);
break;
case PMBUS_VIRT_READ_PIN_MAX:
if (data->id != adm1276) {
if (data->id == adm1275) {
ret = -ENXIO;
break;
}
@ -95,7 +129,7 @@ static int adm1275_read_word_data(struct i2c_client *client, int page, int reg)
case PMBUS_VIRT_RESET_VIN_HISTORY:
break;
case PMBUS_VIRT_RESET_PIN_HISTORY:
if (data->id != adm1276)
if (data->id == adm1275)
ret = -ENXIO;
break;
default:
@ -163,6 +197,19 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
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;
@ -171,6 +218,7 @@ static int adm1275_read_byte_data(struct i2c_client *client, int page, int reg)
}
static const struct i2c_device_id adm1275_id[] = {
{ "adm1075", adm1075 },
{ "adm1275", adm1275 },
{ "adm1276", adm1276 },
{ }
@ -229,7 +277,8 @@ static int adm1275_probe(struct i2c_client *client,
if (device_config < 0)
return device_config;
data = kzalloc(sizeof(struct adm1275_data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(struct adm1275_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -250,7 +299,14 @@ static int adm1275_probe(struct i2c_client *client,
info->read_byte_data = adm1275_read_byte_data;
info->write_word_data = adm1275_write_word_data;
if (config & ADM1275_VRANGE) {
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;
@ -270,6 +326,31 @@ static int adm1275_probe(struct i2c_client *client,
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] |=
@ -297,24 +378,7 @@ static int adm1275_probe(struct i2c_client *client,
break;
}
ret = pmbus_do_probe(client, id, info);
if (ret)
goto err_mem;
return 0;
err_mem:
kfree(data);
return ret;
}
static int adm1275_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct adm1275_data *data = to_adm1275_data(info);
pmbus_do_remove(client);
kfree(data);
return 0;
return pmbus_do_probe(client, id, info);
}
static struct i2c_driver adm1275_driver = {
@ -322,22 +386,12 @@ static struct i2c_driver adm1275_driver = {
.name = "adm1275",
},
.probe = adm1275_probe,
.remove = adm1275_remove,
.remove = pmbus_do_remove,
.id_table = adm1275_id,
};
static int __init adm1275_init(void)
{
return i2c_add_driver(&adm1275_driver);
}
static void __exit adm1275_exit(void)
{
i2c_del_driver(&adm1275_driver);
}
module_i2c_driver(adm1275_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
MODULE_LICENSE("GPL");
module_init(adm1275_init);
module_exit(adm1275_exit);

View File

@ -176,7 +176,6 @@ static int lm25066_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int config;
int ret;
struct lm25066_data *data;
struct pmbus_driver_info *info;
@ -184,15 +183,14 @@ static int lm25066_probe(struct i2c_client *client,
I2C_FUNC_SMBUS_READ_BYTE_DATA))
return -ENODEV;
data = kzalloc(sizeof(struct lm25066_data), GFP_KERNEL);
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) {
ret = config;
goto err_mem;
}
if (config < 0)
return config;
data->id = id->driver_data;
info = &data->info;
@ -291,28 +289,10 @@ static int lm25066_probe(struct i2c_client *client,
}
break;
default:
ret = -ENODEV;
goto err_mem;
return -ENODEV;
}
ret = pmbus_do_probe(client, id, info);
if (ret)
goto err_mem;
return 0;
err_mem:
kfree(data);
return ret;
}
static int lm25066_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct lm25066_data *data = to_lm25066_data(info);
pmbus_do_remove(client);
kfree(data);
return 0;
return pmbus_do_probe(client, id, info);
}
static const struct i2c_device_id lm25066_id[] = {
@ -330,22 +310,12 @@ static struct i2c_driver lm25066_driver = {
.name = "lm25066",
},
.probe = lm25066_probe,
.remove = lm25066_remove,
.remove = pmbus_do_remove,
.id_table = lm25066_id,
};
static int __init lm25066_init(void)
{
return i2c_add_driver(&lm25066_driver);
}
static void __exit lm25066_exit(void)
{
i2c_del_driver(&lm25066_driver);
}
module_i2c_driver(lm25066_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LM25066/LM5064/LM5066");
MODULE_LICENSE("GPL");
module_init(lm25066_init);
module_exit(lm25066_exit);

View File

@ -287,7 +287,7 @@ MODULE_DEVICE_TABLE(i2c, ltc2978_id);
static int ltc2978_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int chip_id, ret, i;
int chip_id, i;
struct ltc2978_data *data;
struct pmbus_driver_info *info;
@ -295,15 +295,14 @@ static int ltc2978_probe(struct i2c_client *client,
I2C_FUNC_SMBUS_READ_WORD_DATA))
return -ENODEV;
data = kzalloc(sizeof(struct ltc2978_data), GFP_KERNEL);
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) {
ret = chip_id;
goto err_mem;
}
if (chip_id < 0)
return chip_id;
if (chip_id == LTC2978_ID_REV1 || chip_id == LTC2978_ID_REV2) {
data->id = ltc2978;
@ -311,8 +310,7 @@ static int ltc2978_probe(struct i2c_client *client,
data->id = ltc3880;
} else {
dev_err(&client->dev, "Unsupported chip ID 0x%x\n", chip_id);
ret = -ENODEV;
goto err_mem;
return -ENODEV;
}
if (data->id != id->driver_data)
dev_warn(&client->dev,
@ -357,28 +355,10 @@ static int ltc2978_probe(struct i2c_client *client,
data->vout_min[1] = 0xffff;
break;
default:
ret = -ENODEV;
goto err_mem;
return -ENODEV;
}
ret = pmbus_do_probe(client, id, info);
if (ret)
goto err_mem;
return 0;
err_mem:
kfree(data);
return ret;
}
static int ltc2978_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct ltc2978_data *data = to_ltc2978_data(info);
pmbus_do_remove(client);
kfree(data);
return 0;
return pmbus_do_probe(client, id, info);
}
/* This is the driver that will be inserted */
@ -387,22 +367,12 @@ static struct i2c_driver ltc2978_driver = {
.name = "ltc2978",
},
.probe = ltc2978_probe,
.remove = ltc2978_remove,
.remove = pmbus_do_remove,
.id_table = ltc2978_id,
};
static int __init ltc2978_init(void)
{
return i2c_add_driver(&ltc2978_driver);
}
static void __exit ltc2978_exit(void)
{
i2c_del_driver(&ltc2978_driver);
}
module_i2c_driver(ltc2978_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LTC2978 and LTC3880");
MODULE_LICENSE("GPL");
module_init(ltc2978_init);
module_exit(ltc2978_exit);

View File

@ -103,12 +103,6 @@ static int max16064_probe(struct i2c_client *client,
return pmbus_do_probe(client, id, &max16064_info);
}
static int max16064_remove(struct i2c_client *client)
{
pmbus_do_remove(client);
return 0;
}
static const struct i2c_device_id max16064_id[] = {
{"max16064", 0},
{}
@ -122,22 +116,12 @@ static struct i2c_driver max16064_driver = {
.name = "max16064",
},
.probe = max16064_probe,
.remove = max16064_remove,
.remove = pmbus_do_remove,
.id_table = max16064_id,
};
static int __init max16064_init(void)
{
return i2c_add_driver(&max16064_driver);
}
static void __exit max16064_exit(void)
{
i2c_del_driver(&max16064_driver);
}
module_i2c_driver(max16064_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
MODULE_LICENSE("GPL");
module_init(max16064_init);
module_exit(max16064_exit);

View File

@ -25,34 +25,82 @@
#include <linux/i2c.h>
#include "pmbus.h"
enum chips { max34440, max34441 };
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:
@ -68,21 +116,42 @@ static int max34440_read_word_data(struct i2c_client *client, int page, int reg)
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;
@ -216,26 +285,66 @@ static struct pmbus_driver_info max34440_info[] = {
.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)
{
return pmbus_do_probe(client, id, &max34440_info[id->driver_data]);
}
struct max34440_data *data;
static int max34440_remove(struct i2c_client *client)
{
pmbus_do_remove(client);
return 0;
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 */
@ -244,22 +353,12 @@ static struct i2c_driver max34440_driver = {
.name = "max34440",
},
.probe = max34440_probe,
.remove = max34440_remove,
.remove = pmbus_do_remove,
.id_table = max34440_id,
};
static int __init max34440_init(void)
{
return i2c_add_driver(&max34440_driver);
}
static void __exit max34440_exit(void)
{
i2c_del_driver(&max34440_driver);
}
module_i2c_driver(max34440_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
MODULE_LICENSE("GPL");
module_init(max34440_init);
module_exit(max34440_exit);

View File

@ -180,12 +180,6 @@ static int max8688_probe(struct i2c_client *client,
return pmbus_do_probe(client, id, &max8688_info);
}
static int max8688_remove(struct i2c_client *client)
{
pmbus_do_remove(client);
return 0;
}
static const struct i2c_device_id max8688_id[] = {
{"max8688", 0},
{ }
@ -199,22 +193,12 @@ static struct i2c_driver max8688_driver = {
.name = "max8688",
},
.probe = max8688_probe,
.remove = max8688_remove,
.remove = pmbus_do_remove,
.id_table = max8688_id,
};
static int __init max8688_init(void)
{
return i2c_add_driver(&max8688_driver);
}
static void __exit max8688_exit(void)
{
i2c_del_driver(&max8688_driver);
}
module_i2c_driver(max8688_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
MODULE_LICENSE("GPL");
module_init(max8688_init);
module_exit(max8688_exit);

View File

@ -166,33 +166,16 @@ static int pmbus_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct pmbus_driver_info *info;
int ret;
info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
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;
ret = pmbus_do_probe(client, id, info);
if (ret < 0)
goto out;
return 0;
out:
kfree(info);
return ret;
}
static int pmbus_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info;
info = pmbus_get_driver_info(client);
pmbus_do_remove(client);
kfree(info);
return 0;
return pmbus_do_probe(client, id, info);
}
/*
@ -202,12 +185,15 @@ 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},
{}
};
@ -220,22 +206,12 @@ static struct i2c_driver pmbus_driver = {
.name = "pmbus",
},
.probe = pmbus_probe,
.remove = pmbus_remove,
.remove = pmbus_do_remove,
.id_table = pmbus_id,
};
static int __init pmbus_init(void)
{
return i2c_add_driver(&pmbus_driver);
}
static void __exit pmbus_exit(void)
{
i2c_del_driver(&pmbus_driver);
}
module_i2c_driver(pmbus_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("Generic PMBus driver");
MODULE_LICENSE("GPL");
module_init(pmbus_init);
module_exit(pmbus_exit);

View File

@ -146,31 +146,36 @@
* code when reading or writing virtual registers.
*/
#define PMBUS_VIRT_BASE 0x100
#define PMBUS_VIRT_READ_TEMP_MIN (PMBUS_VIRT_BASE + 0)
#define PMBUS_VIRT_READ_TEMP_MAX (PMBUS_VIRT_BASE + 1)
#define PMBUS_VIRT_RESET_TEMP_HISTORY (PMBUS_VIRT_BASE + 2)
#define PMBUS_VIRT_READ_VIN_AVG (PMBUS_VIRT_BASE + 3)
#define PMBUS_VIRT_READ_VIN_MIN (PMBUS_VIRT_BASE + 4)
#define PMBUS_VIRT_READ_VIN_MAX (PMBUS_VIRT_BASE + 5)
#define PMBUS_VIRT_RESET_VIN_HISTORY (PMBUS_VIRT_BASE + 6)
#define PMBUS_VIRT_READ_IIN_AVG (PMBUS_VIRT_BASE + 7)
#define PMBUS_VIRT_READ_IIN_MIN (PMBUS_VIRT_BASE + 8)
#define PMBUS_VIRT_READ_IIN_MAX (PMBUS_VIRT_BASE + 9)
#define PMBUS_VIRT_RESET_IIN_HISTORY (PMBUS_VIRT_BASE + 10)
#define PMBUS_VIRT_READ_PIN_AVG (PMBUS_VIRT_BASE + 11)
#define PMBUS_VIRT_READ_PIN_MAX (PMBUS_VIRT_BASE + 12)
#define PMBUS_VIRT_RESET_PIN_HISTORY (PMBUS_VIRT_BASE + 13)
#define PMBUS_VIRT_READ_VOUT_AVG (PMBUS_VIRT_BASE + 14)
#define PMBUS_VIRT_READ_VOUT_MIN (PMBUS_VIRT_BASE + 15)
#define PMBUS_VIRT_READ_VOUT_MAX (PMBUS_VIRT_BASE + 16)
#define PMBUS_VIRT_RESET_VOUT_HISTORY (PMBUS_VIRT_BASE + 17)
#define PMBUS_VIRT_READ_IOUT_AVG (PMBUS_VIRT_BASE + 18)
#define PMBUS_VIRT_READ_IOUT_MIN (PMBUS_VIRT_BASE + 19)
#define PMBUS_VIRT_READ_IOUT_MAX (PMBUS_VIRT_BASE + 20)
#define PMBUS_VIRT_RESET_IOUT_HISTORY (PMBUS_VIRT_BASE + 21)
#define PMBUS_VIRT_READ_TEMP2_MIN (PMBUS_VIRT_BASE + 22)
#define PMBUS_VIRT_READ_TEMP2_MAX (PMBUS_VIRT_BASE + 23)
#define PMBUS_VIRT_RESET_TEMP2_HISTORY (PMBUS_VIRT_BASE + 24)
#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
@ -364,7 +369,7 @@ 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);
void pmbus_do_remove(struct i2c_client *client);
int pmbus_do_remove(struct i2c_client *client);
const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
*client);

View File

@ -40,11 +40,14 @@
#define PMBUS_IOUT_SENSORS_PER_PAGE 8 /* input, min, max, crit,
lowest, highest, avg,
reset */
#define PMBUS_POUT_SENSORS_PER_PAGE 4 /* input, cap, max, crit */
#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 8 /* input, min, max, lcrit,
crit, lowest, highest,
reset */
#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;
@ -782,7 +785,7 @@ static ssize_t pmbus_set_sensor(struct device *dev,
int ret;
u16 regval;
if (strict_strtol(buf, 10, &val) < 0)
if (kstrtol(buf, 10, &val) < 0)
return -EINVAL;
mutex_lock(&data->update_lock);
@ -1334,6 +1337,17 @@ static const struct pmbus_limit_attr pout_limit_attrs[] = {
.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",
}
};
@ -1388,6 +1402,9 @@ static const struct pmbus_limit_attr temp_limit_attrs[] = {
}, {
.reg = PMBUS_VIRT_READ_TEMP_MIN,
.attr = "lowest",
}, {
.reg = PMBUS_VIRT_READ_TEMP_AVG,
.attr = "average",
}, {
.reg = PMBUS_VIRT_READ_TEMP_MAX,
.attr = "highest",
@ -1423,6 +1440,9 @@ static const struct pmbus_limit_attr temp_limit_attrs2[] = {
}, {
.reg = PMBUS_VIRT_READ_TEMP2_MIN,
.attr = "lowest",
}, {
.reg = PMBUS_VIRT_READ_TEMP2_AVG,
.attr = "average",
}, {
.reg = PMBUS_VIRT_READ_TEMP2_MAX,
.attr = "highest",
@ -1676,7 +1696,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
| I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV;
data = kzalloc(sizeof(*data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (!data) {
dev_err(&client->dev, "No memory to allocate driver data\n");
return -ENOMEM;
@ -1688,8 +1708,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
/* 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");
ret = -ENODEV;
goto out_data;
return -ENODEV;
}
if (pdata)
@ -1702,50 +1721,49 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
ret = (*info->identify)(client, info);
if (ret < 0) {
dev_err(&client->dev, "Chip identification failed\n");
goto out_data;
return ret;
}
}
if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
info->pages);
ret = -ENODEV;
goto out_data;
return -ENODEV;
}
ret = pmbus_identify_common(client, data);
if (ret < 0) {
dev_err(&client->dev, "Failed to identify chip capabilities\n");
goto out_data;
return ret;
}
ret = -ENOMEM;
data->sensors = kzalloc(sizeof(struct pmbus_sensor) * data->max_sensors,
GFP_KERNEL);
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");
goto out_data;
return -ENOMEM;
}
data->booleans = kzalloc(sizeof(struct pmbus_boolean)
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");
goto out_sensors;
return -ENOMEM;
}
data->labels = kzalloc(sizeof(struct pmbus_label) * data->max_labels,
GFP_KERNEL);
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");
goto out_booleans;
return -ENOMEM;
}
data->attributes = kzalloc(sizeof(struct attribute *)
* data->max_attributes, GFP_KERNEL);
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");
goto out_labels;
return -ENOMEM;
}
pmbus_find_attributes(client, data);
@ -1756,8 +1774,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
*/
if (!data->num_attributes) {
dev_err(&client->dev, "No attributes found\n");
ret = -ENODEV;
goto out_attributes;
return -ENODEV;
}
/* Register sysfs hooks */
@ -1765,7 +1782,7 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
ret = sysfs_create_group(&client->dev.kobj, &data->group);
if (ret) {
dev_err(&client->dev, "Failed to create sysfs entries\n");
goto out_attributes;
return ret;
}
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
@ -1777,30 +1794,16 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
out_hwmon_device_register:
sysfs_remove_group(&client->dev.kobj, &data->group);
out_attributes:
kfree(data->attributes);
out_labels:
kfree(data->labels);
out_booleans:
kfree(data->booleans);
out_sensors:
kfree(data->sensors);
out_data:
kfree(data);
return ret;
}
EXPORT_SYMBOL_GPL(pmbus_do_probe);
void pmbus_do_remove(struct i2c_client *client)
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);
kfree(data->attributes);
kfree(data->labels);
kfree(data->booleans);
kfree(data->sensors);
kfree(data);
return 0;
}
EXPORT_SYMBOL_GPL(pmbus_do_remove);

View File

@ -155,7 +155,8 @@ static int ucd9000_probe(struct i2c_client *client,
"Device mismatch: Configured %s, detected %s\n",
id->name, mid->name);
data = kzalloc(sizeof(struct ucd9000_data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(struct ucd9000_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
info = &data->info;
@ -164,13 +165,12 @@ static int ucd9000_probe(struct i2c_client *client,
if (ret < 0) {
dev_err(&client->dev,
"Failed to read number of active pages\n");
goto out;
return ret;
}
info->pages = ret;
if (!info->pages) {
dev_err(&client->dev, "No pages configured\n");
ret = -ENODEV;
goto out;
return -ENODEV;
}
/* The internal temperature sensor is always active */
@ -181,8 +181,7 @@ static int ucd9000_probe(struct i2c_client *client,
block_buffer);
if (ret <= 0) {
dev_err(&client->dev, "Failed to read configuration data\n");
ret = -ENODEV;
goto out;
return -ENODEV;
}
for (i = 0; i < ret; i++) {
int page = UCD9000_MON_PAGE(block_buffer[i]);
@ -218,7 +217,7 @@ static int ucd9000_probe(struct i2c_client *client,
UCD9000_FAN_CONFIG,
data->fan_data[i]);
if (ret < 0)
goto out;
return ret;
}
i2c_smbus_write_byte_data(client, UCD9000_FAN_CONFIG_INDEX, 0);
@ -227,49 +226,21 @@ static int ucd9000_probe(struct i2c_client *client,
| PMBUS_HAVE_FAN34 | PMBUS_HAVE_STATUS_FAN34;
}
ret = pmbus_do_probe(client, mid, info);
if (ret < 0)
goto out;
return 0;
out:
kfree(data);
return ret;
return pmbus_do_probe(client, mid, info);
}
static int ucd9000_remove(struct i2c_client *client)
{
struct ucd9000_data *data;
data = to_ucd9000_data(pmbus_get_driver_info(client));
pmbus_do_remove(client);
kfree(data);
return 0;
}
/* This is the driver that will be inserted */
static struct i2c_driver ucd9000_driver = {
.driver = {
.name = "ucd9000",
},
.probe = ucd9000_probe,
.remove = ucd9000_remove,
.remove = pmbus_do_remove,
.id_table = ucd9000_id,
};
static int __init ucd9000_init(void)
{
return i2c_add_driver(&ucd9000_driver);
}
static void __exit ucd9000_exit(void)
{
i2c_del_driver(&ucd9000_driver);
}
module_i2c_driver(ucd9000_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx");
MODULE_LICENSE("GPL");
module_init(ucd9000_init);
module_exit(ucd9000_exit);

View File

@ -81,7 +81,8 @@ static int ucd9200_probe(struct i2c_client *client,
"Device mismatch: Configured %s, detected %s\n",
id->name, mid->name);
info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
info = devm_kzalloc(&client->dev, sizeof(struct pmbus_driver_info),
GFP_KERNEL);
if (!info)
return -ENOMEM;
@ -89,7 +90,7 @@ static int ucd9200_probe(struct i2c_client *client,
block_buffer);
if (ret < 0) {
dev_err(&client->dev, "Failed to read phase information\n");
goto out;
return ret;
}
/*
@ -106,8 +107,7 @@ static int ucd9200_probe(struct i2c_client *client,
}
if (!info->pages) {
dev_err(&client->dev, "No rails configured\n");
ret = -ENODEV;
goto out;
return -ENODEV;
}
dev_info(&client->dev, "%d rails configured\n", info->pages);
@ -137,7 +137,7 @@ static int ucd9200_probe(struct i2c_client *client,
if (ret < 0) {
dev_err(&client->dev,
"Failed to initialize PHASE registers\n");
goto out;
return ret;
}
}
if (info->pages > 1)
@ -160,48 +160,21 @@ static int ucd9200_probe(struct i2c_client *client,
if (mid->driver_data == ucd9240)
info->func[0] |= PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12;
ret = pmbus_do_probe(client, mid, info);
if (ret < 0)
goto out;
return 0;
out:
kfree(info);
return ret;
return pmbus_do_probe(client, mid, info);
}
static int ucd9200_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info;
info = pmbus_get_driver_info(client);
pmbus_do_remove(client);
kfree(info);
return 0;
}
/* This is the driver that will be inserted */
static struct i2c_driver ucd9200_driver = {
.driver = {
.name = "ucd9200",
},
.probe = ucd9200_probe,
.remove = ucd9200_remove,
.remove = pmbus_do_remove,
.id_table = ucd9200_id,
};
static int __init ucd9200_init(void)
{
return i2c_add_driver(&ucd9200_driver);
}
static void __exit ucd9200_exit(void)
{
i2c_del_driver(&ucd9200_driver);
}
module_i2c_driver(ucd9200_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x");
MODULE_LICENSE("GPL");
module_init(ucd9200_init);
module_exit(ucd9200_exit);

View File

@ -28,7 +28,8 @@
#include <linux/delay.h>
#include "pmbus.h"
enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105 };
enum chips { zl2004, zl2005, zl2006, zl2008, zl2105, zl2106, zl6100, zl6105,
zl9101, zl9117 };
struct zl6100_data {
int id;
@ -152,6 +153,8 @@ static const struct i2c_device_id zl6100_id[] = {
{"zl2106", zl2106},
{"zl6100", zl6100},
{"zl6105", zl6105},
{"zl9101", zl9101},
{"zl9117", zl9117},
{ }
};
MODULE_DEVICE_TABLE(i2c, zl6100_id);
@ -193,7 +196,8 @@ static int zl6100_probe(struct i2c_client *client,
"Device mismatch: Configured %s, detected %s\n",
id->name, mid->name);
data = kzalloc(sizeof(struct zl6100_data), GFP_KERNEL);
data = devm_kzalloc(&client->dev, sizeof(struct zl6100_data),
GFP_KERNEL);
if (!data)
return -ENOMEM;
@ -223,7 +227,8 @@ static int zl6100_probe(struct i2c_client *client,
ret = i2c_smbus_read_word_data(client, ZL6100_MFR_CONFIG);
if (ret < 0)
goto err_mem;
return ret;
if (ret & ZL6100_MFR_XTEMP_ENABLE)
info->func[0] |= PMBUS_HAVE_TEMP2;
@ -235,24 +240,7 @@ static int zl6100_probe(struct i2c_client *client,
info->write_word_data = zl6100_write_word_data;
info->write_byte = zl6100_write_byte;
ret = pmbus_do_probe(client, mid, info);
if (ret)
goto err_mem;
return 0;
err_mem:
kfree(data);
return ret;
}
static int zl6100_remove(struct i2c_client *client)
{
const struct pmbus_driver_info *info = pmbus_get_driver_info(client);
const struct zl6100_data *data = to_zl6100_data(info);
pmbus_do_remove(client);
kfree(data);
return 0;
return pmbus_do_probe(client, mid, info);
}
static struct i2c_driver zl6100_driver = {
@ -260,22 +248,12 @@ static struct i2c_driver zl6100_driver = {
.name = "zl6100",
},
.probe = zl6100_probe,
.remove = zl6100_remove,
.remove = pmbus_do_remove,
.id_table = zl6100_id,
};
static int __init zl6100_init(void)
{
return i2c_add_driver(&zl6100_driver);
}
static void __exit zl6100_exit(void)
{
i2c_del_driver(&zl6100_driver);
}
module_i2c_driver(zl6100_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
MODULE_LICENSE("GPL");
module_init(zl6100_init);
module_exit(zl6100_exit);

View File

@ -1,5 +1,5 @@
/***************************************************************************
* Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com> *
* Copyright (C) 2010-2012 Hans de Goede <hdegoede@redhat.com> *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
@ -79,6 +79,7 @@ static const char * const SCH5627_IN_LABELS[SCH5627_NO_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];
@ -453,6 +454,9 @@ 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);
@ -574,6 +578,11 @@ static int __devinit sch5627_probe(struct platform_device *pdev)
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:

Some files were not shown because too many files have changed in this diff Show More