diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-05 15:55:36 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-05 15:55:36 -0700 |
commit | 161d2e0a195292a8a67b0f5c48e12a9984f75dac (patch) | |
tree | 4f3c516ab41737b1e51a58ca3d5f8cca421ae949 | |
parent | c489d98c8c81a898cfed6bec193cca2006f956aa (diff) | |
parent | fce9626cd93abaf1ef21b361f8a0fa493cc855b2 (diff) |
Merge tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging
Pull hwmon updates from Guenter Roeck:
"Notable changes:
- Heiko Schocher provided a driver for TI TMP103.
- Kamil Debski provided a driver for pwm-controlled fans.
- Neelesh Gupta provided a driver for power, fan rpm, voltage and
temperature reporting on powerpc/powernv systems.
- Scott Kanowitz provided a driver supporting Lattice's POWR1220
power manager IC.
- Richard Zhu provided a pmbus front-end driver for TPS40422.
- Frans Klaver added support for TMP112 to the lm75 driver.
- Johannes Pointner added support for EPCOS B57330V2103 to the
ntc_thermistor driver.
- Guenter Roeck added support for TMP441 and TMP442 to the tmp421
driver.
- Axel Lin converted several drivers to the new hwmon API (36 of
them, if I counted correctly), and cleaned up many of the drivers
along the way.
There are also a number of patches fixing bugs discovered while
testing Axel's changes"
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (88 commits)
hwmon: (g762) Use of_property_read_u32 at appropriate place
hwmon: (sis5595) Prevent overflow problem when writing large limits
hwmon: (gpio-fan) Prevent overflow problem when writing large limits
hwmon: (ibmpowernv) Use of_property_read_u32 at appropriate place
hwmon: (lm85) Convert to devm_hwmon_device_register_with_groups
hwmon: (lm85) Avoid forward declaration
hwmon: (lm78) Convert to devm_hwmon_device_register_with_groups
hwmon: (max6697) Use of_property_read_bool at appropriate places
hwmon: (pwm-fan) Make SENSORS_PWM_FAN depend on OF
hwmon: (pwm-fan) Remove duplicate dev_set_drvdata call
hwmon: (nct6775) Remove num_attr_groups from struct nct6775_data
hwmon: (nct6775) Update module description and Kconfig for NCT6106D and NCT6791D
hwmon: (adt7411) Convert to devm_hwmon_device_register_with_groups
hwmon: (g762) Convert to hwmon_device_register_with_groups
hwmon: (emc2103) Convert to devm_hwmon_device_register_with_groups
hwmon: (smsc47m1) Avoid forward declaration
hwmon: (smsc47m192) Convert to devm_hwmon_device_register_with_groups
hwmon: (smsc47m192) Avoid forward declaration
hwmon: (max1668) Make max1668_addr_list array const
hwmon: (max6639) Make normal_i2c array const
...
81 files changed, 4258 insertions, 3885 deletions
diff --git a/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt new file mode 100644 index 000000000000..f93242be60a1 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/ibmpowernv.txt @@ -0,0 +1,23 @@ +IBM POWERNV platform sensors +---------------------------- + +Required node properties: +- compatible: must be one of + "ibm,opal-sensor-cooling-fan" + "ibm,opal-sensor-amb-temp" + "ibm,opal-sensor-power-supply" + "ibm,opal-sensor-power" +- sensor-id: an opaque id provided by the firmware to the kernel, identifies a + given sensor and its attribute data + +Example sensors node: + +cooling-fan#8-data { + sensor-id = <0x7052107>; + compatible = "ibm,opal-sensor-cooling-fan"; +}; + +amb-temp#1-thrs { + sensor-id = <0x5096000>; + compatible = "ibm,opal-sensor-amb-temp"; +}; diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt index b117b2e9e1a7..2391e5c41999 100644 --- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt +++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt @@ -3,6 +3,7 @@ NTC Thermistor hwmon sensors Requires node properties: - "compatible" value : one of + "epcos,b57330v2103" "murata,ncp15wb473" "murata,ncp18wb473" "murata,ncp21wb473" diff --git a/Documentation/devicetree/bindings/hwmon/pwm-fan.txt b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt new file mode 100644 index 000000000000..610757ce4492 --- /dev/null +++ b/Documentation/devicetree/bindings/hwmon/pwm-fan.txt @@ -0,0 +1,12 @@ +Bindings for a fan connected to the PWM lines + +Required properties: +- compatible : "pwm-fan" +- pwms : the PWM that is used to control the PWM fan + +Example: + pwm-fan { + compatible = "pwm-fan"; + status = "okay"; + pwms = <&pwm 0 10000 0>; + }; diff --git a/Documentation/devicetree/bindings/i2c/trivial-devices.txt b/Documentation/devicetree/bindings/i2c/trivial-devices.txt index 1a794213f7d1..37803eb5521e 100644 --- a/Documentation/devicetree/bindings/i2c/trivial-devices.txt +++ b/Documentation/devicetree/bindings/i2c/trivial-devices.txt @@ -84,5 +84,6 @@ stm,m41t80 M41T80 - SERIAL ACCESS RTC WITH ALARMS taos,tsl2550 Ambient Light Sensor with SMBUS/Two Wire Serial Interface ti,tsc2003 I2C Touch-Screen Controller ti,tmp102 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface +ti,tmp103 Low Power Digital Temperature Sensor with SMBUS/Two Wire Serial Interface ti,tmp275 Digital Temperature Sensor winbond,wpct301 i2c trusted platform module (TPM) diff --git a/Documentation/devicetree/bindings/vendor-prefixes.txt b/Documentation/devicetree/bindings/vendor-prefixes.txt index 46a311e728a8..97c9c06132c4 100644 --- a/Documentation/devicetree/bindings/vendor-prefixes.txt +++ b/Documentation/devicetree/bindings/vendor-prefixes.txt @@ -42,6 +42,7 @@ dmo Data Modul AG ebv EBV Elektronik edt Emerging Display Technologies emmicro EM Microelectronic +epcos EPCOS AG epfl Ecole Polytechnique Fédérale de Lausanne epson Seiko Epson Corp. est ESTeem Wireless Modems diff --git a/Documentation/hwmon/ibmpowernv b/Documentation/hwmon/ibmpowernv new file mode 100644 index 000000000000..8826ba29db36 --- /dev/null +++ b/Documentation/hwmon/ibmpowernv @@ -0,0 +1,41 @@ +Kernel Driver IBMPOWERNV +======================== + +Supported systems: + * Any recent IBM P servers based on POWERNV platform + +Author: Neelesh Gupta + +Description +----------- + +This driver implements reading the platform sensors data like temperature/fan/ +voltage/power for 'POWERNV' platform. + +The driver uses the platform device infrastructure. It probes the device tree +for sensor devices during the __init phase and registers them with the 'hwmon'. +'hwmon' populates the 'sysfs' tree having attribute files, each for a given +sensor type and its attribute data. + +All the nodes in the DT appear under "/ibm,opal/sensors" and each valid node in +the DT maps to an attribute file in 'sysfs'. The node exports unique 'sensor-id' +which the driver uses to make an OPAL call to the firmware. + +Usage notes +----------- +The driver is built statically with the kernel by enabling the config +CONFIG_SENSORS_IBMPOWERNV. It can also be built as module 'ibmpowernv'. + +Sysfs attributes +---------------- + +fanX_input Measured RPM value. +fanX_min Threshold RPM for alert generation. +fanX_fault 0: No fail condition + 1: Failing fan +tempX_input Measured ambient temperature. +tempX_max Threshold ambient temperature for alert generation. +inX_input Measured power supply voltage +inX_fault 0: No fail condition. + 1: Failing power supply. +power1_input System power consumption (microWatt) diff --git a/Documentation/hwmon/lm75 b/Documentation/hwmon/lm75 index 2560a9c6d445..c6a5ff1b4641 100644 --- a/Documentation/hwmon/lm75 +++ b/Documentation/hwmon/lm75 @@ -42,13 +42,14 @@ Supported chips: Addresses scanned: none Datasheet: Publicly available at the ST website http://www.st.com/internet/analog/product/121769.jsp - * Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, TMP275 - Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp175', 'tmp75', 'tmp275' + * Texas Instruments TMP100, TMP101, TMP105, TMP112, TMP75, TMP175, TMP275 + Prefixes: 'tmp100', 'tmp101', 'tmp105', 'tmp112', 'tmp175', 'tmp75', 'tmp275' Addresses scanned: none Datasheet: Publicly available at the Texas Instruments website http://www.ti.com/product/tmp100 http://www.ti.com/product/tmp101 http://www.ti.com/product/tmp105 + http://www.ti.com/product/tmp112 http://www.ti.com/product/tmp75 http://www.ti.com/product/tmp175 http://www.ti.com/product/tmp275 diff --git a/Documentation/hwmon/ntc_thermistor b/Documentation/hwmon/ntc_thermistor index 057b77029f26..c5e05e2900a3 100644 --- a/Documentation/hwmon/ntc_thermistor +++ b/Documentation/hwmon/ntc_thermistor @@ -6,6 +6,11 @@ Supported thermistors from Murata: Prefixes: 'ncp15wb473', 'ncp18wb473', 'ncp21wb473', 'ncp03wb473', 'ncp15wl333' Datasheet: Publicly available at Murata +Supported thermistors from EPCOS: +* EPCOS NTC Thermistors B57330V2103 + Prefixes: b57330v2103 + Datasheet: Publicly available at EPCOS + Other NTC thermistors can be supported simply by adding compensation tables; e.g., NCP15WL333 support is added by the table ncpXXwl333. diff --git a/Documentation/hwmon/pmbus b/Documentation/hwmon/pmbus index cf756ed48ff9..a3557da8f5b4 100644 --- a/Documentation/hwmon/pmbus +++ b/Documentation/hwmon/pmbus @@ -23,12 +23,11 @@ Supported chips: 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' + * Texas Instruments TPS40400 + Prefixes: 'tps40400' Addresses scanned: - Datasheets: http://www.ti.com/lit/gpn/tps40400 - http://www.ti.com/lit/gpn/tps40422 * Generic PMBus devices Prefix: 'pmbus' Addresses scanned: - diff --git a/Documentation/hwmon/powr1220 b/Documentation/hwmon/powr1220 new file mode 100644 index 000000000000..21e44f71ae6e --- /dev/null +++ b/Documentation/hwmon/powr1220 @@ -0,0 +1,45 @@ +Kernel driver powr1220 +================== + +Supported chips: + * Lattice POWR1220AT8 + Prefix: 'powr1220' + Addresses scanned: none + Datasheet: Publicly available at the Lattice website + http://www.latticesemi.com/ + +Author: Scott Kanowitz <scott.kanowitz@gmail.com> + +Description +----------- + +This driver supports the Lattice POWR1220AT8 chip. The POWR1220 +includes voltage monitoring for 14 inputs as well as trim settings +for output voltages and GPIOs. This driver implements the voltage +monitoring portion of the chip. + +Voltages are sampled by a 12-bit ADC with a step size of 2 mV. +An in-line attenuator allows measurements from 0 to 6 V. The +attenuator is enabled or disabled depending on the setting of the +input's max value. The driver will enable the attenuator for any +value over the low measurement range maximum of 2 V. + +The input naming convention is as follows: + +driver name pin name +in0 VMON1 +in1 VMON2 +in2 VMON3 +in2 VMON4 +in4 VMON5 +in5 VMON6 +in6 VMON7 +in7 VMON8 +in8 VMON9 +in9 VMON10 +in10 VMON11 +in11 VMON12 +in12 VCCA +in13 VCCINP + +The ADC readings are updated on request with a minimum period of 1s. diff --git a/Documentation/hwmon/pwm-fan b/Documentation/hwmon/pwm-fan new file mode 100644 index 000000000000..18529d2e3bcf --- /dev/null +++ b/Documentation/hwmon/pwm-fan @@ -0,0 +1,17 @@ +Kernel driver pwm-fan +===================== + +This driver enables the use of a PWM module to drive a fan. It uses the +generic PWM interface thus it is hardware independent. It can be used on +many SoCs, as long as the SoC supplies a PWM line driver that exposes +the generic PWM API. + +Author: Kamil Debski <k.debski@samsung.com> + +Description +----------- + +The driver implements a simple interface for driving a fan connected to +a PWM output. It uses the generic PWM interface, thus it can be used with +a range of SoCs. The driver exposes the fan to the user space through +the hwmon's sysfs interface. diff --git a/Documentation/hwmon/tmp103 b/Documentation/hwmon/tmp103 new file mode 100644 index 000000000000..ec00a15645ba --- /dev/null +++ b/Documentation/hwmon/tmp103 @@ -0,0 +1,28 @@ +Kernel driver tmp103 +==================== + +Supported chips: + * Texas Instruments TMP103 + Prefix: 'tmp103' + Addresses scanned: none + Product info and datasheet: http://www.ti.com/product/tmp103 + +Author: + Heiko Schocher <hs@denx.de> + +Description +----------- + +The TMP103 is a digital output temperature sensor in a four-ball +wafer chip-scale package (WCSP). The TMP103 is capable of reading +temperatures to a resolution of 1°C. The TMP103 is specified for +operation over a temperature range of –40°C to +125°C. + +Resolution: 8 Bits +Accuracy: ±1°C Typ (–10°C to +100°C) + +The driver provides the common sysfs-interface for temperatures (see +Documentation/hwmon/sysfs-interface under Temperatures). + +Please refer how to instantiate this driver: +Documentation/i2c/instantiating-devices diff --git a/Documentation/hwmon/tmp421 b/Documentation/hwmon/tmp421 index 0cf07f824741..9e6fe5549ca1 100644 --- a/Documentation/hwmon/tmp421 +++ b/Documentation/hwmon/tmp421 @@ -8,12 +8,20 @@ Supported chips: Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html * Texas Instruments TMP422 Prefix: 'tmp422' - Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f + Addresses scanned: I2C 0x4c, 0x4d, 0x4e and 0x4f Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html * Texas Instruments TMP423 Prefix: 'tmp423' - Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f + Addresses scanned: I2C 0x4c and 0x4d Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html + * Texas Instruments TMP441 + Prefix: 'tmp441' + Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f + Datasheet: http://www.ti.com/product/tmp441 + * Texas Instruments TMP442 + Prefix: 'tmp442' + Addresses scanned: I2C 0x4c and 0x4d + Datasheet: http://www.ti.com/product/tmp442 Authors: Andre Prendel <andre.prendel@gmx.de> @@ -21,13 +29,13 @@ Authors: Description ----------- -This driver implements support for Texas Instruments TMP421, TMP422 -and TMP423 temperature sensor chips. These chips implement one local -and up to one (TMP421), up to two (TMP422) or up to three (TMP423) -remote sensors. Temperature is measured in degrees Celsius. The chips -are wired over I2C/SMBus and specified over a temperature range of -40 -to +125 degrees Celsius. Resolution for both the local and remote -channels is 0.0625 degree C. +This driver implements support for Texas Instruments TMP421, TMP422, +TMP423, TMP441, and TMP442 temperature sensor chips. These chips +implement one local and up to one (TMP421, TMP441), up to two (TMP422, +TMP442) or up to three (TMP423) remote sensors. Temperature is measured +in degrees Celsius. The chips are wired over I2C/SMBus and specified +over a temperature range of -40 to +125 degrees Celsius. Resolution +for both the local and remote channels is 0.0625 degree C. The chips support only temperature measurement. The driver exports the temperature values via the following sysfs files: diff --git a/Documentation/hwmon/tps40422 b/Documentation/hwmon/tps40422 new file mode 100644 index 000000000000..24bb0688d515 --- /dev/null +++ b/Documentation/hwmon/tps40422 @@ -0,0 +1,64 @@ +Kernel driver tps40422 +====================== + +Supported chips: + * TI TPS40422 + Prefix: 'tps40422' + Addresses scanned: - + Datasheet: http://www.ti.com/lit/gpn/tps40422 + +Author: Zhu Laiwen <richard.zhu@nsn.com> + + +Description +----------- + +This driver supports TI TPS40422 Dual-Output or Two-Phase Synchronous Buck +Controller with PMBus + +The driver is a client driver to the core PMBus driver. +Please see Documentation/hwmon/pmbus for details on PMBus client drivers. + + +Usage Notes +----------- + +This driver does not auto-detect devices. You will have to instantiate the +devices explicitly. Please see Documentation/i2c/instantiating-devices for +details. + + +Platform data support +--------------------- + +The driver supports standard PMBus driver platform data. + + +Sysfs entries +------------- + +The following attributes are supported. + +in[1-2]_label "vout[1-2]" +in[1-2]_input Measured voltage. From READ_VOUT register. +in[1-2]_alarm voltage alarm. + +curr[1-2]_input Measured current. From READ_IOUT register. +curr[1-2]_label "iout[1-2]" +curr1_max Maximum current. From IOUT_OC_WARN_LIMIT register. +curr1_crit Critical maximum current. From IOUT_OC_FAULT_LIMIT register. +curr1_max_alarm Current high alarm. From IOUT_OC_WARN_LIMIT status. +curr1_crit_alarm Current critical high alarm. From IOUT_OC_FAULT status. +curr2_alarm Current high alarm. From IOUT_OC_WARNING status. + +temp1_input Measured temperature. From READ_TEMPERATURE_2 register on page 0. +temp1_max Maximum temperature. From OT_WARN_LIMIT register. +temp1_crit Critical high temperature. From OT_FAULT_LIMIT register. +temp1_max_alarm Chip temperature high alarm. Set by comparing + READ_TEMPERATURE_2 on page 0 with OT_WARN_LIMIT if TEMP_OT_WARNING + status is set. +temp1_crit_alarm Chip temperature critical high alarm. Set by comparing + READ_TEMPERATURE_2 on page 0 with OT_FAULT_LIMIT if TEMP_OT_FAULT + status is set. +temp2_input Measured temperature. From READ_TEMPERATURE_2 register on page 1. +temp2_alarm Chip temperature alarm on page 1. diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 02d3d85829f3..f00d048aa583 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -554,6 +554,17 @@ config SENSORS_IBMPEX This driver can also be built as a module. If so, the module will be called ibmpex. +config SENSORS_IBMPOWERNV + tristate "IBM POWERNV platform sensors" + depends on PPC_POWERNV + default y + help + If you say yes here you get support for the temperature/fan/power + sensors on your PowerNV platform. + + This driver can also be built as a module. If so, the module + will be called ibmpowernv. + config SENSORS_IIO_HWMON tristate "Hwmon driver that uses channels specified via iio maps" depends on IIO @@ -608,6 +619,18 @@ config SENSORS_JC42 This driver can also be built as a module. If so, the module will be called jc42. +config SENSORS_POWR1220 + tristate "Lattice POWR1220 Power Monitoring" + depends on I2C + default n + help + If you say yes here you get access to the hardware monitoring + functions of the Lattice POWR1220 isp Power Supply Monitoring, + Sequencing and Margining Controller. + + This driver can also be built as a module. If so, the module + will be called powr1220. + config SENSORS_LINEAGE tristate "Lineage Compact Power Line Power Entry Module" depends on I2C @@ -882,8 +905,8 @@ config SENSORS_LM75 - NXP's LM75A - ST Microelectronics STDS75 - TelCom (now Microchip) TCN75 - - Texas Instruments TMP100, TMP101, TMP105, TMP75, TMP175, - TMP275 + - Texas Instruments TMP100, TMP101, TMP105, TMP112, TMP75, + TMP175, TMP275 This driver supports driver model based binding through board specific I2C device tables. @@ -1061,7 +1084,7 @@ config SENSORS_NTC_THERMISTOR Currently, this driver supports NCP15WB473, NCP18WB473, NCP21WB473, NCP03WB473, and NCP15WL333 - from Murata. + from Murata and B57330V2103 from EPCOS. This driver can also be built as a module. If so, the module will be called ntc-thermistor. @@ -1082,8 +1105,8 @@ config SENSORS_NCT6775 select HWMON_VID help If you say yes here you get support for the hardware monitoring - functionality of the Nuvoton NCT6775F, NCT6776F, NCT6779D - and compatible Super-I/O chips. This driver replaces the + functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D, + NCT6791D and compatible Super-I/O chips. This driver replaces the w83627ehf driver for NCT6775F and NCT6776F. This driver can also be built as a module. If so, the module @@ -1105,6 +1128,17 @@ config SENSORS_PCF8591 source drivers/hwmon/pmbus/Kconfig +config SENSORS_PWM_FAN + tristate "PWM fan" + depends on (PWM && OF) || COMPILE_TEST + help + If you say yes here you get support for fans connected to PWM lines. + The driver uses the generic PWM interface, thus it will work on a + variety of SoCs. + + This driver can also be built as a module. If so, the module + will be called pwm-fan. + config SENSORS_SHT15 tristate "Sensiron humidity and temperature sensors. SHT15 and compat." depends on GPIOLIB @@ -1393,6 +1427,17 @@ config SENSORS_TMP102 This driver can also be built as a module. If so, the module will be called tmp102. +config SENSORS_TMP103 + tristate "Texas Instruments TMP103" + depends on I2C + select REGMAP_I2C + help + If you say yes here you get support for Texas Instruments TMP103 + sensor chips. + + This driver can also be built as a module. If so, the module + will be called tmp103. + config SENSORS_TMP401 tristate "Texas Instruments TMP401 and compatibles" depends on I2C @@ -1408,7 +1453,7 @@ config SENSORS_TMP421 depends on I2C help If you say yes here you get support for Texas Instruments TMP421, - TMP422 and TMP423 temperature sensor chips. + TMP422, TMP423, TMP441, and TMP442 temperature sensor chips. This driver can also be built as a module. If so, the module will be called tmp421. diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 3dc0f02f71d2..be28152c9848 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -71,6 +71,7 @@ obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o +obj-$(CONFIG_SENSORS_IBMPOWERNV)+= ibmpowernv.o obj-$(CONFIG_SENSORS_IIO_HWMON) += iio_hwmon.o obj-$(CONFIG_SENSORS_INA209) += ina209.o obj-$(CONFIG_SENSORS_INA2XX) += ina2xx.o @@ -120,6 +121,8 @@ obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o +obj-$(CONFIG_SENSORS_POWR1220) += powr1220.o +obj-$(CONFIG_SENSORS_PWM_FAN) += pwm-fan.o obj-$(CONFIG_SENSORS_S3C) += s3c-hwmon.o obj-$(CONFIG_SENSORS_SCH56XX_COMMON)+= sch56xx-common.o obj-$(CONFIG_SENSORS_SCH5627) += sch5627.o @@ -135,6 +138,7 @@ obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o obj-$(CONFIG_SENSORS_AMC6821) += amc6821.o obj-$(CONFIG_SENSORS_THMC50) += thmc50.o obj-$(CONFIG_SENSORS_TMP102) += tmp102.o +obj-$(CONFIG_SENSORS_TMP103) += tmp103.o obj-$(CONFIG_SENSORS_TMP401) += tmp401.o obj-$(CONFIG_SENSORS_TMP421) += tmp421.o obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 5d501adc3e54..763490acc0df 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -39,7 +39,7 @@ static u8 AD7414_REG_LIMIT[] = { AD7414_REG_T_HIGH, AD7414_REG_T_LOW }; struct ad7414_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex lock; /* atomic read data updates */ char valid; /* !=0 if following fields are valid */ unsigned long next_update; /* In jiffies */ @@ -72,8 +72,8 @@ static inline int ad7414_write(struct i2c_client *client, u8 reg, u8 value) static struct ad7414_data *ad7414_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct ad7414_data *data = i2c_get_clientdata(client); + struct ad7414_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; mutex_lock(&data->lock); @@ -127,8 +127,8 @@ static ssize_t set_max_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct ad7414_data *data = i2c_get_clientdata(client); + struct ad7414_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int index = to_sensor_dev_attr(attr)->index; u8 reg = AD7414_REG_LIMIT[index]; long temp; @@ -164,7 +164,7 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 3); static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 4); -static struct attribute *ad7414_attributes[] = { +static struct attribute *ad7414_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, @@ -173,27 +173,25 @@ static struct attribute *ad7414_attributes[] = { NULL }; -static const struct attribute_group ad7414_group = { - .attrs = ad7414_attributes, -}; +ATTRIBUTE_GROUPS(ad7414); static int ad7414_probe(struct i2c_client *client, const struct i2c_device_id *dev_id) { + struct device *dev = &client->dev; struct ad7414_data *data; + struct device *hwmon_dev; int conf; - int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_READ_WORD_DATA)) return -EOPNOTSUPP; - data = devm_kzalloc(&client->dev, sizeof(struct ad7414_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct ad7414_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->lock); dev_info(&client->dev, "chip found\n"); @@ -201,38 +199,16 @@ static int ad7414_probe(struct i2c_client *client, /* Make sure the chip is powered up. */ conf = i2c_smbus_read_byte_data(client, AD7414_REG_CONF); if (conf < 0) - dev_warn(&client->dev, - "ad7414_probe unable to read config register.\n"); + dev_warn(dev, "ad7414_probe unable to read config register.\n"); else { conf &= ~(1 << 7); i2c_smbus_write_byte_data(client, AD7414_REG_CONF, conf); } - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &ad7414_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &ad7414_group); - return err; -} - -static int ad7414_remove(struct i2c_client *client) -{ - struct ad7414_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ad7414_group); - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, + client->name, + data, ad7414_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id ad7414_id[] = { @@ -246,7 +222,6 @@ static struct i2c_driver ad7414_driver = { .name = "ad7414", }, .probe = ad7414_probe, - .remove = ad7414_remove, .id_table = ad7414_id, }; diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index 57d4a6295675..a01b731ba5d7 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -44,8 +44,7 @@ static const u8 AD7418_REG_TEMP[] = { AD7418_REG_TEMP_IN, AD7418_REG_TEMP_OS }; struct ad7418_data { - struct device *hwmon_dev; - struct attribute_group attrs; + struct i2c_client *client; enum chips type; struct mutex lock; int adc_max; /* number of ADC channels */ @@ -55,48 +54,10 @@ struct ad7418_data { u16 in[4]; }; -static int ad7418_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int ad7418_remove(struct i2c_client *client); - -static const struct i2c_device_id ad7418_id[] = { - { "ad7416", ad7416 }, - { "ad7417", ad7417 }, - { "ad7418", ad7418 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, ad7418_id); - -static struct i2c_driver ad7418_driver = { - .driver = { - .name = "ad7418", - }, - .probe = ad7418_probe, - .remove = ad7418_remove, - .id_table = ad7418_id, -}; - -static void ad7418_init_client(struct i2c_client *client) -{ - struct ad7418_data *data = i2c_get_clientdata(client); - - int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); - if (reg < 0) { - dev_err(&client->dev, "cannot read configuration register\n"); - } else { - dev_info(&client->dev, "configuring for mode 1\n"); - i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe); - - if (data->type == ad7417 || data->type == ad7418) - i2c_smbus_write_byte_data(client, - AD7418_REG_CONF2, 0x00); - } -} - static struct ad7418_data *ad7418_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct ad7418_data *data = i2c_get_clientdata(client); + struct ad7418_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; mutex_lock(&data->lock); @@ -165,8 +126,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct ad7418_data *data = i2c_get_clientdata(client); + struct ad7418_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; int ret = kstrtol(buf, 10, &temp); @@ -193,14 +154,15 @@ static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_adc, NULL, 1); static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_adc, NULL, 2); static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_adc, NULL, 3); -static struct attribute *ad7416_attributes[] = { +static struct attribute *ad7416_attrs[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, NULL }; +ATTRIBUTE_GROUPS(ad7416); -static struct attribute *ad7417_attributes[] = { +static struct attribute *ad7417_attrs[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, @@ -210,83 +172,100 @@ static struct attribute *ad7417_attributes[] = { &sensor_dev_attr_in4_input.dev_attr.attr, NULL }; +ATTRIBUTE_GROUPS(ad7417); -static struct attribute *ad7418_attributes[] = { +static struct attribute *ad7418_attrs[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, NULL }; +ATTRIBUTE_GROUPS(ad7418); + +static void ad7418_init_client(struct i2c_client *client) +{ + struct ad7418_data *data = i2c_get_clientdata(client); + + int reg = i2c_smbus_read_byte_data(client, AD7418_REG_CONF); + if (reg < 0) { + dev_err(&client->dev, "cannot read configuration register\n"); + } else { + dev_info(&client->dev, "configuring for mode 1\n"); + i2c_smbus_write_byte_data(client, AD7418_REG_CONF, reg & 0xfe); + + if (data->type == ad7417 || data->type == ad7418) + i2c_smbus_write_byte_data(client, + AD7418_REG_CONF2, 0x00); + } +} static int ad7418_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct i2c_adapter *adapter = client->adapter; struct ad7418_data *data; - int err; + struct device *hwmon_dev; + const struct attribute_group **attr_groups = NULL; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) return -EOPNOTSUPP; - data = devm_kzalloc(&client->dev, sizeof(struct ad7418_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct ad7418_data), GFP_KERNEL); if (!data) return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->lock); + data->client = client; data->type = id->driver_data; switch (data->type) { case ad7416: data->adc_max = 0; - data->attrs.attrs = ad7416_attributes; + attr_groups = ad7416_groups; break; case ad7417: data->adc_max = 4; - data->attrs.attrs = ad7417_attributes; + attr_groups = ad7417_groups; break; case ad7418: data->adc_max = 1; - data->attrs.attrs = ad7418_attributes; + attr_groups = ad7418_groups; break; } - dev_info(&client->dev, "%s chip found\n", client->name); + dev_info(dev, "%s chip found\n", client->name); /* Initialize the AD7418 chip */ ad7418_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &data->attrs); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &data->attrs); - return err; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, + client->name, + data, attr_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static int ad7418_remove(struct i2c_client *client) -{ - struct ad7418_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->attrs); - return 0; -} +static const struct i2c_device_id ad7418_id[] = { + { "ad7416", ad7416 }, + { "ad7417", ad7417 }, + { "ad7418", ad7418 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, ad7418_id); + +static struct i2c_driver ad7418_driver = { + .driver = { + .name = "ad7418", + }, + .probe = ad7418_probe, + .id_table = ad7418_id, +}; module_i2c_driver(ad7418_driver); diff --git a/drivers/hwmon/adm1021.c b/drivers/hwmon/adm1021.c index d74241bb278c..1fdcc3e703b9 100644 --- a/drivers/hwmon/adm1021.c +++ b/drivers/hwmon/adm1021.c @@ -98,41 +98,63 @@ struct adm1021_data { u8 remote_temp_offset_prec; }; -static int adm1021_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1021_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1021_init_client(struct i2c_client *client); -static struct adm1021_data *adm1021_update_device(struct device *dev); - /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */ static bool read_only; +static struct adm1021_data *adm1021_update_device(struct device *dev) +{ + struct adm1021_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; -static const struct i2c_device_id adm1021_id[] = { - { "adm1021", adm1021 }, - { "adm1023", adm1023 }, - { "max1617", max1617 }, - { "max1617a", max1617a }, - { "thmc10", thmc10 }, - { "lm84", lm84 }, - { "gl523sm", gl523sm }, - { "mc1066", mc1066 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1021_id); + mutex_lock(&data->update_lock); -/* This is the driver that will be inserted */ -static struct i2c_driver adm1021_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1021", - }, - .probe = adm1021_probe, - .id_table = adm1021_id, - .detect = adm1021_detect, - .address_list = normal_i2c, -}; + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i; + + dev_dbg(dev, "Starting adm1021 update\n"); + + for (i = 0; i < 2; i++) { + data->temp[i] = 1000 * + (s8) i2c_smbus_read_byte_data( + client, ADM1021_REG_TEMP(i)); + data->temp_max[i] = 1000 * + (s8) i2c_smbus_read_byte_data( + client, ADM1021_REG_TOS_R(i)); + if (data->type != lm84) { + data->temp_min[i] = 1000 * + (s8) i2c_smbus_read_byte_data(client, + ADM1021_REG_THYST_R(i)); + } + } + data->alarms = i2c_smbus_read_byte_data(client, + ADM1021_REG_STATUS) & 0x7c; + if (data->type == adm1023) { + /* + * The ADM1023 provides 3 extra bits of precision for + * the remote sensor in extra registers. + */ + data->temp[1] += 125 * (i2c_smbus_read_byte_data( + client, ADM1023_REG_REM_TEMP_PREC) >> 5); + data->temp_max[1] += 125 * (i2c_smbus_read_byte_data( + client, ADM1023_REG_REM_TOS_PREC) >> 5); + data->temp_min[1] += 125 * (i2c_smbus_read_byte_data( + client, ADM1023_REG_REM_THYST_PREC) >> 5); + data->remote_temp_offset = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_OFFSET); + data->remote_temp_offset_prec = + i2c_smbus_read_byte_data(client, + ADM1023_REG_REM_OFFSET_PREC); + } + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, char *buf) @@ -411,6 +433,15 @@ static int adm1021_detect(struct i2c_client *client, return 0; } +static void adm1021_init_client(struct i2c_client *client) +{ + /* Enable ADC and disable suspend mode */ + i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, + i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF); + /* Set Conversion rate to 1/sec (this can be tinkered with) */ + i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); +} + static int adm1021_probe(struct i2c_client *client, const struct i2c_device_id *id) { @@ -440,69 +471,29 @@ static int adm1021_probe(struct i2c_client *client, return PTR_ERR_OR_ZERO(hwmon_dev); } -static void adm1021_init_client(struct i2c_client *client) -{ - /* Enable ADC and disable suspend mode */ - i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W, - i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF); - /* Set Conversion rate to 1/sec (this can be tinkered with) */ - i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04); -} - -static struct adm1021_data *adm1021_update_device(struct device *dev) -{ - struct adm1021_data *data = dev_get_drvdata(dev); - struct i2c_client *client = data->client; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - int i; - - dev_dbg(dev, "Starting adm1021 update\n"); - - for (i = 0; i < 2; i++) { - data->temp[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_TEMP(i)); - data->temp_max[i] = 1000 * - (s8) i2c_smbus_read_byte_data( - client, ADM1021_REG_TOS_R(i)); - if (data->type != lm84) { - data->temp_min[i] = 1000 * - (s8) i2c_smbus_read_byte_data(client, - ADM1021_REG_THYST_R(i)); - } - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM1021_REG_STATUS) & 0x7c; - if (data->type == adm1023) { - /* - * The ADM1023 provides 3 extra bits of precision for - * the remote sensor in extra registers. - */ - data->temp[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_TEMP_PREC) >> 5); - data->temp_max[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_TOS_PREC) >> 5); - data->temp_min[1] += 125 * (i2c_smbus_read_byte_data( - client, ADM1023_REG_REM_THYST_PREC) >> 5); - data->remote_temp_offset = - i2c_smbus_read_byte_data(client, - ADM1023_REG_REM_OFFSET); - data->remote_temp_offset_prec = - i2c_smbus_read_byte_data(client, - ADM1023_REG_REM_OFFSET_PREC); - } - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); +static const struct i2c_device_id adm1021_id[] = { + { "adm1021", adm1021 }, + { "adm1023", adm1023 }, + { "max1617", max1617 }, + { "max1617a", max1617a }, + { "thmc10", thmc10 }, + { "lm84", lm84 }, + { "gl523sm", gl523sm }, + { "mc1066", mc1066 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1021_id); - return data; -} +static struct i2c_driver adm1021_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm1021", + }, + .probe = adm1021_probe, + .id_table = adm1021_id, + .detect = adm1021_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm1021_driver); diff --git a/drivers/hwmon/adm1025.c b/drivers/hwmon/adm1025.c index 9ffc4c8ca8b5..d3d0e8cf27b4 100644 --- a/drivers/hwmon/adm1025.c +++ b/drivers/hwmon/adm1025.c @@ -103,46 +103,12 @@ static const int in_scale[6] = { 2500, 2250, 3300, 5000, 12000, 3300 }; (val) + 500) / 1000)) /* - * Functions declaration - */ - -static int adm1025_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1025_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1025_init_client(struct i2c_client *client); -static int adm1025_remove(struct i2c_client *client); -static struct adm1025_data *adm1025_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id adm1025_id[] = { - { "adm1025", adm1025 }, - { "ne1619", ne1619 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1025_id); - -static struct i2c_driver adm1025_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1025", - }, - .probe = adm1025_probe, - .remove = adm1025_remove, - .id_table = adm1025_id, - .detect = adm1025_detect, - .address_list = normal_i2c, -}; - -/* * Client data (each client gets its own) */ struct adm1025_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -158,6 +124,51 @@ struct adm1025_data { u8 vrm; }; +static struct adm1025_data *adm1025_update_device(struct device *dev) +{ + struct adm1025_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { + int i; + + dev_dbg(&client->dev, "Updating data.\n"); + for (i = 0; i < 6; i++) { + data->in[i] = i2c_smbus_read_byte_data(client, + ADM1025_REG_IN(i)); + data->in_min[i] = i2c_smbus_read_byte_data(client, + ADM1025_REG_IN_MIN(i)); + data->in_max[i] = i2c_smbus_read_byte_data(client, + ADM1025_REG_IN_MAX(i)); + } + for (i = 0; i < 2; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + ADM1025_REG_TEMP(i)); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + ADM1025_REG_TEMP_LOW(i)); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + ADM1025_REG_TEMP_HIGH(i)); + } + data->alarms = i2c_smbus_read_byte_data(client, + ADM1025_REG_STATUS1) + | (i2c_smbus_read_byte_data(client, + ADM1025_REG_STATUS2) << 8); + data->vid = (i2c_smbus_read_byte_data(client, + ADM1025_REG_VID) & 0x0f) + | ((i2c_smbus_read_byte_data(client, + ADM1025_REG_VID4) & 0x01) << 4); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + /* * Sysfs stuff */ @@ -217,8 +228,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); + struct adm1025_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -238,8 +249,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); + struct adm1025_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -273,8 +284,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); + struct adm1025_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -294,8 +305,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int index = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); + struct adm1025_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -470,51 +481,6 @@ static int adm1025_detect(struct i2c_client *client, return 0; } -static int adm1025_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1025_data *data; - int err; - u8 config; - - data = devm_kzalloc(&client->dev, sizeof(struct adm1025_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the ADM1025 chip */ - adm1025_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1025_group); - if (err) - return err; - - /* Pin 11 is either in4 (+12V) or VID4 */ - config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); - if (!(config & 0x20)) { - err = sysfs_create_group(&client->dev.kobj, &adm1025_group_in4); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &adm1025_group); - sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); - return err; -} - static void adm1025_init_client(struct i2c_client *client) { u8 reg; @@ -557,61 +523,54 @@ static void adm1025_init_client(struct i2c_client *client) (reg&0x7E)|0x01); } -static int adm1025_remove(struct i2c_client *client) +static int adm1025_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct adm1025_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1025_group); - sysfs_remove_group(&client->dev.kobj, &adm1025_group_in4); - - return 0; -} + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct adm1025_data *data; + u8 config; -static struct adm1025_data *adm1025_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1025_data *data = i2c_get_clientdata(client); + data = devm_kzalloc(dev, sizeof(struct adm1025_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - mutex_lock(&data->update_lock); + i2c_set_clientdata(client, data); + data->client = client; + mutex_init(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) { - int i; + /* Initialize the ADM1025 chip */ + adm1025_init_client(client); - dev_dbg(&client->dev, "Updating data.\n"); - for (i = 0; i < 6; i++) { - data->in[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN(i)); - data->in_min[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN_MIN(i)); - data->in_max[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_IN_MAX(i)); - } - for (i = 0; i < 2; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP(i)); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP_LOW(i)); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - ADM1025_REG_TEMP_HIGH(i)); - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM1025_REG_STATUS1) - | (i2c_smbus_read_byte_data(client, - ADM1025_REG_STATUS2) << 8); - data->vid = (i2c_smbus_read_byte_data(client, - ADM1025_REG_VID) & 0x0f) - | ((i2c_smbus_read_byte_data(client, - ADM1025_REG_VID4) & 0x01) << 4); + /* sysfs hooks */ + data->groups[0] = &adm1025_group; + /* Pin 11 is either in4 (+12V) or VID4 */ + config = i2c_smbus_read_byte_data(client, ADM1025_REG_CONFIG); + if (!(config & 0x20)) + data->groups[1] = &adm1025_group_in4; - data->last_updated = jiffies; - data->valid = 1; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - mutex_unlock(&data->update_lock); +static const struct i2c_device_id adm1025_id[] = { + { "adm1025", adm1025 }, + { "ne1619", ne1619 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1025_id); - return data; -} +static struct i2c_driver adm1025_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm1025", + }, + .probe = adm1025_probe, + .id_table = adm1025_id, + .detect = adm1025_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm1025_driver); diff --git a/drivers/hwmon/adm1026.c b/drivers/hwmon/adm1026.c index b3498acb9ab4..ca8430f92564 100644 --- a/drivers/hwmon/adm1026.c +++ b/drivers/hwmon/adm1026.c @@ -266,7 +266,8 @@ struct pwm_data { }; struct adm1026_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; int valid; /* !=0 if following fields are valid */ @@ -298,37 +299,6 @@ struct adm1026_data { u8 config3; /* Register value */ }; -static int adm1026_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1026_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adm1026_remove(struct i2c_client *client); -static int adm1026_read_value(struct i2c_client *client, u8 reg); -static int adm1026_write_value(struct i2c_client *client, u8 reg, int value); -static void adm1026_print_gpio(struct i2c_client *client); -static void adm1026_fixup_gpio(struct i2c_client *client); -static struct adm1026_data *adm1026_update_device(struct device *dev); -static void adm1026_init_client(struct i2c_client *client); - - -static const struct i2c_device_id adm1026_id[] = { - { "adm1026", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1026_id); - -static struct i2c_driver adm1026_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1026", - }, - .probe = adm1026_probe, - .remove = adm1026_remove, - .id_table = adm1026_id, - .detect = adm1026_detect, - .address_list = normal_i2c, -}; - static int adm1026_read_value(struct i2c_client *client, u8 reg) { int res; @@ -357,212 +327,10 @@ static int adm1026_write_value(struct i2c_client *client, u8 reg, int value) return res; } -static void adm1026_init_client(struct i2c_client *client) -{ - int value, i; - struct adm1026_data *data = i2c_get_clientdata(client); - - dev_dbg(&client->dev, "Initializing device\n"); - /* Read chip config */ - data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); - data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); - data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); - - /* Inform user of chip config */ - dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n", - data->config1); - if ((data->config1 & CFG1_MONITOR) == 0) { - dev_dbg(&client->dev, - "Monitoring not currently enabled.\n"); - } - if (data->config1 & CFG1_INT_ENABLE) { - dev_dbg(&client->dev, - "SMBALERT interrupts are enabled.\n"); - } - if (data->config1 & CFG1_AIN8_9) { - dev_dbg(&client->dev, - "in8 and in9 enabled. temp3 disabled.\n"); - } else { - dev_dbg(&client->dev, - "temp3 enabled. in8 and in9 disabled.\n"); - } - if (data->config1 & CFG1_THERM_HOT) { - dev_dbg(&client->dev, - "Automatic THERM, PWM, and temp limits enabled.\n"); - } - - if (data->config3 & CFG3_GPIO16_ENABLE) { - dev_dbg(&client->dev, - "GPIO16 enabled. THERM pin disabled.\n"); - } else { - dev_dbg(&client->dev, - "THERM pin enabled. GPIO16 disabled.\n"); - } - if (data->config3 & CFG3_VREF_250) - dev_dbg(&client->dev, "Vref is 2.50 Volts.\n"); - else - dev_dbg(&client->dev, "Vref is 1.82 Volts.\n"); - /* Read and pick apart the existing GPIO configuration */ - value = 0; - for (i = 0; i <= 15; ++i) { - if ((i & 0x03) == 0) { - value = adm1026_read_value(client, - ADM1026_REG_GPIO_CFG_0_3 + i / 4); - } - data->gpio_config[i] = value & 0x03; - value >>= 2; - } - data->gpio_config[16] = (data->config3 >> 6) & 0x03; - - /* ... and then print it */ - adm1026_print_gpio(client); - - /* - * If the user asks us to reprogram the GPIO config, then - * do it now. - */ - if (gpio_input[0] != -1 || gpio_output[0] != -1 - || gpio_inverted[0] != -1 || gpio_normal[0] != -1 - || gpio_fan[0] != -1) { - adm1026_fixup_gpio(client); - } - - /* - * WE INTENTIONALLY make no changes to the limits, - * offsets, pwms, fans and zones. If they were - * configured, we don't want to mess with them. - * If they weren't, the default is 100% PWM, no - * control and will suffice until 'sensors -s' - * can be run by the user. We DO set the default - * value for pwm1.auto_pwm_min to its maximum - * so that enabling automatic pwm fan control - * without first setting a value for pwm1.auto_pwm_min - * will not result in potentially dangerous fan speed decrease. - */ - data->pwm1.auto_pwm_min = 255; - /* Start monitoring */ - value = adm1026_read_value(client, ADM1026_REG_CONFIG1); - /* Set MONITOR, clear interrupt acknowledge and s/w reset */ - value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); - dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); - data->config1 = value; - adm1026_write_value(client, ADM1026_REG_CONFIG1, value); - - /* initialize fan_div[] to hardware defaults */ - value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | - (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); - for (i = 0; i <= 7; ++i) { - data->fan_div[i] = DIV_FROM_REG(value & 0x03); - value >>= 2; - } -} - -static void adm1026_print_gpio(struct i2c_client *client) -{ - struct adm1026_data *data = i2c_get_clientdata(client); - int i; - - dev_dbg(&client->dev, "GPIO config is:\n"); - for (i = 0; i <= 7; ++i) { - if (data->config2 & (1 << i)) { - dev_dbg(&client->dev, "\t%sGP%s%d\n", - data->gpio_config[i] & 0x02 ? "" : "!", - data->gpio_config[i] & 0x01 ? "OUT" : "IN", - i); - } else { - dev_dbg(&client->dev, "\tFAN%d\n", i); - } - } - for (i = 8; i <= 15; ++i) { - dev_dbg(&client->dev, "\t%sGP%s%d\n", - data->gpio_config[i] & 0x02 ? "" : "!", - data->gpio_config[i] & 0x01 ? "OUT" : "IN", - i); - } - if (data->config3 & CFG3_GPIO16_ENABLE) { - dev_dbg(&client->dev, "\t%sGP%s16\n", - data->gpio_config[16] & 0x02 ? "" : "!", - data->gpio_config[16] & 0x01 ? "OUT" : "IN"); - } else { - /* GPIO16 is THERM */ - dev_dbg(&client->dev, "\tTHERM\n"); - } -} - -static void adm1026_fixup_gpio(struct i2c_client *client) -{ - struct adm1026_data *data = i2c_get_clientdata(client); - int i; - int value; - - /* Make the changes requested. */ - /* - * We may need to unlock/stop monitoring or soft-reset the - * chip before we can make changes. This hasn't been - * tested much. FIXME - */ - - /* Make outputs */ - for (i = 0; i <= 16; ++i) { - if (gpio_output[i] >= 0 && gpio_output[i] <= 16) - data->gpio_config[gpio_output[i]] |= 0x01; - /* if GPIO0-7 is output, it isn't a FAN tach */ - if (gpio_output[i] >= 0 && gpio_output[i] <= 7) - data->config2 |= 1 << gpio_output[i]; - } - - /* Input overrides output */ - for (i = 0; i <= 16; ++i) { - if (gpio_input[i] >= 0 && gpio_input[i] <= 16) - data->gpio_config[gpio_input[i]] &= ~0x01; - /* if GPIO0-7 is input, it isn't a FAN tach */ - if (gpio_input[i] >= 0 && gpio_input[i] <= 7) - data->config2 |= 1 << gpio_input[i]; - } - - /* Inverted */ - for (i = 0; i <= 16; ++i) { - if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) - data->gpio_config[gpio_inverted[i]] &= ~0x02; - } - - /* Normal overrides inverted */ - for (i = 0; i <= 16; ++i) { - if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) - data->gpio_config[gpio_normal[i]] |= 0x02; - } - - /* Fan overrides input and output */ - for (i = 0; i <= 7; ++i) { - if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) - data->config2 &= ~(1 << gpio_fan[i]); - } - - /* Write new configs to registers */ - adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); - data->config3 = (data->config3 & 0x3f) - | ((data->gpio_config[16] & 0x03) << 6); - adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); - for (i = 15, value = 0; i >= 0; --i) { - value <<= 2; - value |= data->gpio_config[i] & 0x03; - if ((i & 0x03) == 0) { - adm1026_write_value(client, - ADM1026_REG_GPIO_CFG_0_3 + i/4, - value); - value = 0; - } - } - - /* Print the new config */ - adm1026_print_gpio(client); -} - - static struct adm1026_data *adm1026_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int i; long value, alarms, gpio; @@ -728,8 +496,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -756,8 +524,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -815,8 +583,8 @@ static ssize_t show_in16_min(struct device *dev, struct device_attribute *attr, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -840,8 +608,8 @@ static ssize_t show_in16_max(struct device *dev, struct device_attribute *attr, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -888,8 +656,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -923,8 +691,8 @@ fan_offset(8); /* Adjust fan_min to account for new fan divisor */ static void fixup_fan_min(struct device *dev, int fan, int old_div) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int new_min; int new_div = data->fan_div[fan]; @@ -952,8 +720,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int orig_div, new_div; int err; @@ -1024,8 +792,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1053,8 +821,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1097,8 +865,8 @@ static ssize_t set_temp_offset(struct device *dev, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1153,8 +921,8 @@ static ssize_t set_temp_auto_point1_temp(struct device *dev, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1192,8 +960,8 @@ static ssize_t show_temp_crit_enable(struct device *dev, static ssize_t set_temp_crit_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -1233,8 +1001,8 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct adm1026_data *data = i2c_get_clientdata(client); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1268,8 +1036,8 @@ 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1378,8 +1146,8 @@ static ssize_t show_alarm_mask(struct device *dev, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long mask; long val; int err; @@ -1420,8 +1188,8 @@ static ssize_t show_gpio(struct device *dev, struct device_attribute *attr, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long gpio; long val; int err; @@ -1453,8 +1221,8 @@ static ssize_t show_gpio_mask(struct device *dev, struct device_attribute *attr, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long mask; long val; int err; @@ -1487,8 +1255,8 @@ static ssize_t show_pwm_reg(struct device *dev, struct device_attribute *attr, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; if (data->pwm1.enable == 1) { long val; @@ -1517,8 +1285,8 @@ 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -1553,8 +1321,8 @@ static ssize_t show_pwm_enable(struct device *dev, 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); + struct adm1026_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int old_enable; unsigned long val; int err; @@ -1829,18 +1597,220 @@ static int adm1026_detect(struct i2c_client *client, return 0; } +static void adm1026_print_gpio(struct i2c_client *client) +{ + struct adm1026_data *data = i2c_get_clientdata(client); + int i; + + dev_dbg(&client->dev, "GPIO config is:\n"); + for (i = 0; i <= 7; ++i) { + if (data->config2 & (1 << i)) { + dev_dbg(&client->dev, "\t%sGP%s%d\n", + data->gpio_config[i] & 0x02 ? "" : "!", + data->gpio_config[i] & 0x01 ? "OUT" : "IN", + i); + } else { + dev_dbg(&client->dev, "\tFAN%d\n", i); + } + } + for (i = 8; i <= 15; ++i) { + dev_dbg(&client->dev, "\t%sGP%s%d\n", + data->gpio_config[i] & 0x02 ? "" : "!", + data->gpio_config[i] & 0x01 ? "OUT" : "IN", + i); + } + if (data->config3 & CFG3_GPIO16_ENABLE) { + dev_dbg(&client->dev, "\t%sGP%s16\n", + data->gpio_config[16] & 0x02 ? "" : "!", + data->gpio_config[16] & 0x01 ? "OUT" : "IN"); + } else { + /* GPIO16 is THERM */ + dev_dbg(&client->dev, "\tTHERM\n"); + } +} + +static void adm1026_fixup_gpio(struct i2c_client *client) +{ + struct adm1026_data *data = i2c_get_clientdata(client); + int i; + int value; + + /* Make the changes requested. */ + /* + * We may need to unlock/stop monitoring or soft-reset the + * chip before we can make changes. This hasn't been + * tested much. FIXME + */ + + /* Make outputs */ + for (i = 0; i <= 16; ++i) { + if (gpio_output[i] >= 0 && gpio_output[i] <= 16) + data->gpio_config[gpio_output[i]] |= 0x01; + /* if GPIO0-7 is output, it isn't a FAN tach */ + if (gpio_output[i] >= 0 && gpio_output[i] <= 7) + data->config2 |= 1 << gpio_output[i]; + } + + /* Input overrides output */ + for (i = 0; i <= 16; ++i) { + if (gpio_input[i] >= 0 && gpio_input[i] <= 16) + data->gpio_config[gpio_input[i]] &= ~0x01; + /* if GPIO0-7 is input, it isn't a FAN tach */ + if (gpio_input[i] >= 0 && gpio_input[i] <= 7) + data->config2 |= 1 << gpio_input[i]; + } + + /* Inverted */ + for (i = 0; i <= 16; ++i) { + if (gpio_inverted[i] >= 0 && gpio_inverted[i] <= 16) + data->gpio_config[gpio_inverted[i]] &= ~0x02; + } + + /* Normal overrides inverted */ + for (i = 0; i <= 16; ++i) { + if (gpio_normal[i] >= 0 && gpio_normal[i] <= 16) + data->gpio_config[gpio_normal[i]] |= 0x02; + } + + /* Fan overrides input and output */ + for (i = 0; i <= 7; ++i) { + if (gpio_fan[i] >= 0 && gpio_fan[i] <= 7) + data->config2 &= ~(1 << gpio_fan[i]); + } + + /* Write new configs to registers */ + adm1026_write_value(client, ADM1026_REG_CONFIG2, data->config2); + data->config3 = (data->config3 & 0x3f) + | ((data->gpio_config[16] & 0x03) << 6); + adm1026_write_value(client, ADM1026_REG_CONFIG3, data->config3); + for (i = 15, value = 0; i >= 0; --i) { + value <<= 2; + value |= data->gpio_config[i] & 0x03; + if ((i & 0x03) == 0) { + adm1026_write_value(client, + ADM1026_REG_GPIO_CFG_0_3 + i/4, + value); + value = 0; + } + } + + /* Print the new config */ + adm1026_print_gpio(client); +} + +static void adm1026_init_client(struct i2c_client *client) +{ + int value, i; + struct adm1026_data *data = i2c_get_clientdata(client); + + dev_dbg(&client->dev, "Initializing device\n"); + /* Read chip config */ + data->config1 = adm1026_read_value(client, ADM1026_REG_CONFIG1); + data->config2 = adm1026_read_value(client, ADM1026_REG_CONFIG2); + data->config3 = adm1026_read_value(client, ADM1026_REG_CONFIG3); + + /* Inform user of chip config */ + dev_dbg(&client->dev, "ADM1026_REG_CONFIG1 is: 0x%02x\n", + data->config1); + if ((data->config1 & CFG1_MONITOR) == 0) { + dev_dbg(&client->dev, + "Monitoring not currently enabled.\n"); + } + if (data->config1 & CFG1_INT_ENABLE) { + dev_dbg(&client->dev, + "SMBALERT interrupts are enabled.\n"); + } + if (data->config1 & CFG1_AIN8_9) { + dev_dbg(&client->dev, + "in8 and in9 enabled. temp3 disabled.\n"); + } else { + dev_dbg(&client->dev, + "temp3 enabled. in8 and in9 disabled.\n"); + } + if (data->config1 & CFG1_THERM_HOT) { + dev_dbg(&client->dev, + "Automatic THERM, PWM, and temp limits enabled.\n"); + } + + if (data->config3 & CFG3_GPIO16_ENABLE) { + dev_dbg(&client->dev, + "GPIO16 enabled. THERM pin disabled.\n"); + } else { + dev_dbg(&client->dev, + "THERM pin enabled. GPIO16 disabled.\n"); + } + if (data->config3 & CFG3_VREF_250) + dev_dbg(&client->dev, "Vref is 2.50 Volts.\n"); + else + dev_dbg(&client->dev, "Vref is 1.82 Volts.\n"); + /* Read and pick apart the existing GPIO configuration */ + value = 0; + for (i = 0; i <= 15; ++i) { + if ((i & 0x03) == 0) { + value = adm1026_read_value(client, + ADM1026_REG_GPIO_CFG_0_3 + i / 4); + } + data->gpio_config[i] = value & 0x03; + value >>= 2; + } + data->gpio_config[16] = (data->config3 >> 6) & 0x03; + + /* ... and then print it */ + adm1026_print_gpio(client); + + /* + * If the user asks us to reprogram the GPIO config, then + * do it now. + */ + if (gpio_input[0] != -1 || gpio_output[0] != -1 + || gpio_inverted[0] != -1 || gpio_normal[0] != -1 + || gpio_fan[0] != -1) { + adm1026_fixup_gpio(client); + } + + /* + * WE INTENTIONALLY make no changes to the limits, + * offsets, pwms, fans and zones. If they were + * configured, we don't want to mess with them. + * If they weren't, the default is 100% PWM, no + * control and will suffice until 'sensors -s' + * can be run by the user. We DO set the default + * value for pwm1.auto_pwm_min to its maximum + * so that enabling automatic pwm fan control + * without first setting a value for pwm1.auto_pwm_min + * will not result in potentially dangerous fan speed decrease. + */ + data->pwm1.auto_pwm_min = 255; + /* Start monitoring */ + value = adm1026_read_value(client, ADM1026_REG_CONFIG1); + /* Set MONITOR, clear interrupt acknowledge and s/w reset */ + value = (value | CFG1_MONITOR) & (~CFG1_INT_CLEAR & ~CFG1_RESET); + dev_dbg(&client->dev, "Setting CONFIG to: 0x%02x\n", value); + data->config1 = value; + adm1026_write_value(client, ADM1026_REG_CONFIG1, value); + + /* initialize fan_div[] to hardware defaults */ + value = adm1026_read_value(client, ADM1026_REG_FAN_DIV_0_3) | + (adm1026_read_value(client, ADM1026_REG_FAN_DIV_4_7) << 8); + for (i = 0; i <= 7; ++i) { + data->fan_div[i] = DIV_FROM_REG(value & 0x03); + value >>= 2; + } +} + static int adm1026_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct adm1026_data *data; - int err; - data = devm_kzalloc(&client->dev, sizeof(struct adm1026_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct adm1026_data), GFP_KERNEL); if (!data) return -ENOMEM; i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); /* Set the VRM version */ @@ -1849,48 +1819,34 @@ static int adm1026_probe(struct i2c_client *client, /* Initialize the ADM1026 chip */ adm1026_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1026_group); - if (err) - return err; + /* sysfs hooks */ + data->groups[0] = &adm1026_group; if (data->config1 & CFG1_AIN8_9) - err = sysfs_create_group(&client->dev.kobj, - &adm1026_group_in8_9); + data->groups[1] = &adm1026_group_in8_9; else - err = sysfs_create_group(&client->dev.kobj, - &adm1026_group_temp3); - if (err) - goto exitremove; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exitremove; - } - - return 0; + data->groups[1] = &adm1026_group_temp3; - /* Error out and cleanup code */ -exitremove: - sysfs_remove_group(&client->dev.kobj, &adm1026_group); - if (data->config1 & CFG1_AIN8_9) - sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); - else - sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); - return err; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static int adm1026_remove(struct i2c_client *client) -{ - struct adm1026_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1026_group); - if (data->config1 & CFG1_AIN8_9) - sysfs_remove_group(&client->dev.kobj, &adm1026_group_in8_9); - else - sysfs_remove_group(&client->dev.kobj, &adm1026_group_temp3); - return 0; -} +static const struct i2c_device_id adm1026_id[] = { + { "adm1026", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1026_id); + +static struct i2c_driver adm1026_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm1026", + }, + .probe = adm1026_probe, + .id_table = adm1026_id, + .detect = adm1026_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm1026_driver); diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 2804571b269e..8c5cdb560258 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -106,45 +106,11 @@ static const u8 ADM1029_REG_FAN_DIV[] = { }; /* - * Functions declaration - */ - -static int adm1029_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1029_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adm1029_remove(struct i2c_client *client); -static struct adm1029_data *adm1029_update_device(struct device *dev); -static int adm1029_init_client(struct i2c_client *client); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id adm1029_id[] = { - { "adm1029", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1029_id); - -static struct i2c_driver adm1029_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1029", - }, - .probe = adm1029_probe, - .remove = adm1029_remove, - .id_table = adm1029_id, - .detect = adm1029_detect, - .address_list = normal_i2c, -}; - -/* * Client data (each client gets its own) */ struct adm1029_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -156,6 +122,50 @@ struct adm1029_data { }; /* + * function that update the status of the chips (temperature for example) + */ +static struct adm1029_data *adm1029_update_device(struct device *dev) +{ + struct adm1029_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + + mutex_lock(&data->update_lock); + /* + * Use the "cache" Luke, don't recheck values + * if there are already checked not a long time later + */ + if (time_after(jiffies, data->last_updated + HZ * 2) + || !data->valid) { + int nr; + + dev_dbg(&client->dev, "Updating adm1029 data\n"); + + for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) { + data->temp[nr] = + i2c_smbus_read_byte_data(client, + ADM1029_REG_TEMP[nr]); + } + for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) { + data->fan[nr] = + i2c_smbus_read_byte_data(client, + ADM1029_REG_FAN[nr]); + } + for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) { + data->fan_div[nr] = + i2c_smbus_read_byte_data(client, + ADM1029_REG_FAN_DIV[nr]); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* * Sysfs stuff */ @@ -197,8 +207,8 @@ show_fan_div(struct device *dev, struct device_attribute *devattr, char *buf) static ssize_t set_fan_div(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1029_data *data = i2c_get_clientdata(client); + struct adm1029_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); u8 reg; long val; @@ -270,7 +280,7 @@ static SENSOR_DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR, static SENSOR_DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR, show_fan_div, set_fan_div, 1); -static struct attribute *adm1029_attributes[] = { +static struct attribute *adm1029_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, @@ -289,9 +299,7 @@ static struct attribute *adm1029_attributes[] = { NULL }; -static const struct attribute_group adm1029_group = { - .attrs = adm1029_attributes, -}; +ATTRIBUTE_GROUPS(adm1029); /* * Real code @@ -340,48 +348,10 @@ static int adm1029_detect(struct i2c_client *client, return 0; } -static int adm1029_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1029_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct adm1029_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* - * Initialize the ADM1029 chip - * Check config register - */ - if (adm1029_init_client(client) == 0) - return -ENODEV; - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1029_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - - exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &adm1029_group); - return err; -} - static int adm1029_init_client(struct i2c_client *client) { u8 config; + config = i2c_smbus_read_byte_data(client, ADM1029_REG_CONFIG); if ((config & 0x10) == 0) { i2c_smbus_write_byte_data(client, ADM1029_REG_CONFIG, @@ -396,59 +366,49 @@ static int adm1029_init_client(struct i2c_client *client) return 1; } -static int adm1029_remove(struct i2c_client *client) +static int adm1029_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct adm1029_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1029_group); + struct device *dev = &client->dev; + struct adm1029_data *data; + struct device *hwmon_dev; - return 0; -} + data = devm_kzalloc(dev, sizeof(struct adm1029_data), GFP_KERNEL); + if (!data) + return -ENOMEM; -/* - * function that update the status of the chips (temperature for example) - */ -static struct adm1029_data *adm1029_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct adm1029_data *data = i2c_get_clientdata(client); + data->client = client; + mutex_init(&data->update_lock); - mutex_lock(&data->update_lock); /* - * Use the "cache" Luke, don't recheck values - * if there are already checked not a long time later + * Initialize the ADM1029 chip + * Check config register */ - if (time_after(jiffies, data->last_updated + HZ * 2) - || !data->valid) { - int nr; - - dev_dbg(&client->dev, "Updating adm1029 data\n"); - - for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_TEMP); nr++) { - data->temp[nr] = - i2c_smbus_read_byte_data(client, - ADM1029_REG_TEMP[nr]); - } - for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN); nr++) { - data->fan[nr] = - i2c_smbus_read_byte_data(client, - ADM1029_REG_FAN[nr]); - } - for (nr = 0; nr < ARRAY_SIZE(ADM1029_REG_FAN_DIV); nr++) { - data->fan_div[nr] = - i2c_smbus_read_byte_data(client, - ADM1029_REG_FAN_DIV[nr]); - } + if (adm1029_init_client(client) == 0) + return -ENODEV; - data->last_updated = jiffies; - data->valid = 1; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + adm1029_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - mutex_unlock(&data->update_lock); +static const struct i2c_device_id adm1029_id[] = { + { "adm1029", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1029_id); - return data; -} +static struct i2c_driver adm1029_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm1029", + }, + .probe = adm1029_probe, + .id_table = adm1029_id, + .detect = adm1029_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm1029_driver); diff --git a/drivers/hwmon/adm1031.c b/drivers/hwmon/adm1031.c index 51c1a5a165ab..a5818980dad7 100644 --- a/drivers/hwmon/adm1031.c +++ b/drivers/hwmon/adm1031.c @@ -74,7 +74,8 @@ typedef u8 auto_chan_table_t[8][2]; /* Each client has this additional data */ struct adm1031_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; int chip_type; char valid; /* !=0 if following fields are valid */ @@ -105,34 +106,6 @@ struct adm1031_data { s8 temp_crit[3]; }; -static int adm1031_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm1031_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm1031_init_client(struct i2c_client *client); -static int adm1031_remove(struct i2c_client *client); -static struct adm1031_data *adm1031_update_device(struct device *dev); - -static const struct i2c_device_id adm1031_id[] = { - { "adm1030", adm1030 }, - { "adm1031", adm1031 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm1031_id); - -/* This is the driver that will be inserted */ -static struct i2c_driver adm1031_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm1031", - }, - .probe = adm1031_probe, - .remove = adm1031_remove, - .id_table = adm1031_id, - .detect = adm1031_detect, - .address_list = normal_i2c, -}; - static inline u8 adm1031_read_value(struct i2c_client *client, u8 reg) { return i2c_smbus_read_byte_data(client, reg); @@ -144,6 +117,96 @@ adm1031_write_value(struct i2c_client *client, u8 reg, unsigned int value) return i2c_smbus_write_byte_data(client, reg, value); } +static struct adm1031_data *adm1031_update_device(struct device *dev) +{ + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + unsigned long next_update; + int chan; + + mutex_lock(&data->update_lock); + + next_update = data->last_updated + + msecs_to_jiffies(data->update_interval); + if (time_after(jiffies, next_update) || !data->valid) { + + dev_dbg(&client->dev, "Starting adm1031 update\n"); + for (chan = 0; + chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { + u8 oldh, newh; + + oldh = + adm1031_read_value(client, ADM1031_REG_TEMP(chan)); + data->ext_temp[chan] = + adm1031_read_value(client, ADM1031_REG_EXT_TEMP); + newh = + adm1031_read_value(client, ADM1031_REG_TEMP(chan)); + if (newh != oldh) { + data->ext_temp[chan] = + adm1031_read_value(client, + ADM1031_REG_EXT_TEMP); +#ifdef DEBUG + oldh = + adm1031_read_value(client, + ADM1031_REG_TEMP(chan)); + + /* oldh is actually newer */ + if (newh != oldh) + dev_warn(&client->dev, + "Remote temperature may be wrong.\n"); +#endif + } + data->temp[chan] = newh; + + data->temp_offset[chan] = + adm1031_read_value(client, + ADM1031_REG_TEMP_OFFSET(chan)); + data->temp_min[chan] = + adm1031_read_value(client, + ADM1031_REG_TEMP_MIN(chan)); + data->temp_max[chan] = + adm1031_read_value(client, + ADM1031_REG_TEMP_MAX(chan)); + data->temp_crit[chan] = + adm1031_read_value(client, + ADM1031_REG_TEMP_CRIT(chan)); + data->auto_temp[chan] = + adm1031_read_value(client, + ADM1031_REG_AUTO_TEMP(chan)); + + } + + data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); + data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); + + data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) + | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); + if (data->chip_type == adm1030) + data->alarm &= 0xc0ff; + + for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); + chan++) { + data->fan_div[chan] = + adm1031_read_value(client, + ADM1031_REG_FAN_DIV(chan)); + data->fan_min[chan] = + adm1031_read_value(client, + ADM1031_REG_FAN_MIN(chan)); + data->fan[chan] = + adm1031_read_value(client, + ADM1031_REG_FAN_SPEED(chan)); + data->pwm[chan] = + (adm1031_read_value(client, + ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; + } + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} #define TEMP_TO_REG(val) (((val) < 0 ? ((val - 500) / 1000) : \ ((val + 500) / 1000))) @@ -280,8 +343,8 @@ static ssize_t set_fan_auto_channel(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; u8 reg; @@ -355,8 +418,8 @@ static ssize_t set_auto_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -385,8 +448,8 @@ static ssize_t set_auto_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -428,8 +491,8 @@ static ssize_t show_pwm(struct device *dev, static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret, reg; @@ -541,8 +604,8 @@ static ssize_t show_fan_min(struct device *dev, static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -565,8 +628,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; u8 tmp; @@ -667,8 +730,8 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -688,8 +751,8 @@ static ssize_t set_temp_offset(struct device *dev, static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -709,8 +772,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -730,8 +793,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_crit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; long val; int ret; @@ -807,8 +870,7 @@ static const unsigned int update_intervals[] = { static ssize_t show_update_interval(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); return sprintf(buf, "%u\n", data->update_interval); } @@ -817,8 +879,8 @@ static ssize_t set_update_interval(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); + struct adm1031_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int i, err; u8 reg; @@ -950,64 +1012,6 @@ static int adm1031_detect(struct i2c_client *client, return 0; } -static int adm1031_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct adm1031_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct adm1031_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->chip_type = id->driver_data; - mutex_init(&data->update_lock); - - if (data->chip_type == adm1030) - data->chan_select_table = &auto_channel_select_table_adm1030; - else - data->chan_select_table = &auto_channel_select_table_adm1031; - - /* Initialize the ADM1031 chip */ - adm1031_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &adm1031_group); - if (err) - return err; - - if (data->chip_type == adm1031) { - err = sysfs_create_group(&client->dev.kobj, &adm1031_group_opt); - if (err) - goto exit_remove; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &adm1031_group); - sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); - return err; -} - -static int adm1031_remove(struct i2c_client *client) -{ - struct adm1031_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm1031_group); - sysfs_remove_group(&client->dev.kobj, &adm1031_group_opt); - return 0; -} - static void adm1031_init_client(struct i2c_client *client) { unsigned int read_val; @@ -1039,96 +1043,57 @@ static void adm1031_init_client(struct i2c_client *client) data->update_interval = update_intervals[i]; } -static struct adm1031_data *adm1031_update_device(struct device *dev) +static int adm1031_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client = to_i2c_client(dev); - struct adm1031_data *data = i2c_get_clientdata(client); - unsigned long next_update; - int chan; - - mutex_lock(&data->update_lock); - - next_update = data->last_updated - + msecs_to_jiffies(data->update_interval); - if (time_after(jiffies, next_update) || !data->valid) { - - dev_dbg(&client->dev, "Starting adm1031 update\n"); - for (chan = 0; - chan < ((data->chip_type == adm1031) ? 3 : 2); chan++) { - u8 oldh, newh; - - oldh = - adm1031_read_value(client, ADM1031_REG_TEMP(chan)); - data->ext_temp[chan] = - adm1031_read_value(client, ADM1031_REG_EXT_TEMP); - newh = - adm1031_read_value(client, ADM1031_REG_TEMP(chan)); - if (newh != oldh) { - data->ext_temp[chan] = - adm1031_read_value(client, - ADM1031_REG_EXT_TEMP); -#ifdef DEBUG - oldh = - adm1031_read_value(client, - ADM1031_REG_TEMP(chan)); + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct adm1031_data *data; - /* oldh is actually newer */ - if (newh != oldh) - dev_warn(&client->dev, - "Remote temperature may be wrong.\n"); -#endif - } - data->temp[chan] = newh; + data = devm_kzalloc(dev, sizeof(struct adm1031_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - data->temp_offset[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_OFFSET(chan)); - data->temp_min[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_MIN(chan)); - data->temp_max[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_MAX(chan)); - data->temp_crit[chan] = - adm1031_read_value(client, - ADM1031_REG_TEMP_CRIT(chan)); - data->auto_temp[chan] = - adm1031_read_value(client, - ADM1031_REG_AUTO_TEMP(chan)); + i2c_set_clientdata(client, data); + data->client = client; + data->chip_type = id->driver_data; + mutex_init(&data->update_lock); - } + if (data->chip_type == adm1030) + data->chan_select_table = &auto_channel_select_table_adm1030; + else + data->chan_select_table = &auto_channel_select_table_adm1031; - data->conf1 = adm1031_read_value(client, ADM1031_REG_CONF1); - data->conf2 = adm1031_read_value(client, ADM1031_REG_CONF2); + /* Initialize the ADM1031 chip */ + adm1031_init_client(client); - data->alarm = adm1031_read_value(client, ADM1031_REG_STATUS(0)) - | (adm1031_read_value(client, ADM1031_REG_STATUS(1)) << 8); - if (data->chip_type == adm1030) - data->alarm &= 0xc0ff; + /* sysfs hooks */ + data->groups[0] = &adm1031_group; + if (data->chip_type == adm1031) + data->groups[1] = &adm1031_group_opt; - for (chan = 0; chan < (data->chip_type == adm1030 ? 1 : 2); - chan++) { - data->fan_div[chan] = - adm1031_read_value(client, - ADM1031_REG_FAN_DIV(chan)); - data->fan_min[chan] = - adm1031_read_value(client, - ADM1031_REG_FAN_MIN(chan)); - data->fan[chan] = - adm1031_read_value(client, - ADM1031_REG_FAN_SPEED(chan)); - data->pwm[chan] = - (adm1031_read_value(client, - ADM1031_REG_PWM) >> (4 * chan)) & 0x0f; - } - data->last_updated = jiffies; - data->valid = 1; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - mutex_unlock(&data->update_lock); +static const struct i2c_device_id adm1031_id[] = { + { "adm1030", adm1030 }, + { "adm1031", adm1031 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm1031_id); - return data; -} +static struct i2c_driver adm1031_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm1031", + }, + .probe = adm1031_probe, + .id_table = adm1031_id, + .detect = adm1031_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm1031_driver); diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 086d02a9ecdc..98114cef1e43 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -130,38 +130,9 @@ static inline unsigned int AOUT_FROM_REG(u8 reg) return SCALE(reg, 1250, 255); } -static int adm9240_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adm9240_detect(struct i2c_client *client, - struct i2c_board_info *info); -static void adm9240_init_client(struct i2c_client *client); -static int adm9240_remove(struct i2c_client *client); -static struct adm9240_data *adm9240_update_device(struct device *dev); - -/* driver data */ -static const struct i2c_device_id adm9240_id[] = { - { "adm9240", adm9240 }, - { "ds1780", ds1780 }, - { "lm81", lm81 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adm9240_id); - -static struct i2c_driver adm9240_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adm9240", - }, - .probe = adm9240_probe, - .remove = adm9240_remove, - .id_table = adm9240_id, - .detect = adm9240_detect, - .address_list = normal_i2c, -}; - /* per client data */ struct adm9240_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; unsigned long last_updated_measure; @@ -181,6 +152,110 @@ struct adm9240_data { u8 vrm; /* -- vrm set on startup, no accessor */ }; +/* write new fan div, callers must hold data->update_lock */ +static void adm9240_write_fan_div(struct i2c_client *client, int nr, + u8 fan_div) +{ + u8 reg, old, shift = (nr + 2) * 2; + + reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV); + old = (reg >> shift) & 3; + reg &= ~(3 << shift); + reg |= (fan_div << shift); + i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg); + dev_dbg(&client->dev, + "fan%d clock divider changed from %u to %u\n", + nr + 1, 1 << old, 1 << fan_div); +} + +static struct adm9240_data *adm9240_update_device(struct device *dev) +{ + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + /* minimum measurement cycle: 1.75 seconds */ + if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) + || !data->valid) { + + for (i = 0; i < 6; i++) { /* read voltages */ + data->in[i] = i2c_smbus_read_byte_data(client, + ADM9240_REG_IN(i)); + } + data->alarms = i2c_smbus_read_byte_data(client, + ADM9240_REG_INT(0)) | + i2c_smbus_read_byte_data(client, + ADM9240_REG_INT(1)) << 8; + + /* + * read temperature: assume temperature changes less than + * 0.5'C per two measurement cycles thus ignore possible + * but unlikely aliasing error on lsb reading. --Grant + */ + data->temp = ((i2c_smbus_read_byte_data(client, + ADM9240_REG_TEMP) << 8) | + i2c_smbus_read_byte_data(client, + ADM9240_REG_TEMP_CONF)) / 128; + + for (i = 0; i < 2; i++) { /* read fans */ + data->fan[i] = i2c_smbus_read_byte_data(client, + ADM9240_REG_FAN(i)); + + /* adjust fan clock divider on overflow */ + if (data->valid && data->fan[i] == 255 && + data->fan_div[i] < 3) { + + adm9240_write_fan_div(client, i, + ++data->fan_div[i]); + + /* adjust fan_min if active, but not to 0 */ + if (data->fan_min[i] < 255 && + data->fan_min[i] >= 2) + data->fan_min[i] /= 2; + } + } + data->last_updated_measure = jiffies; + } + + /* minimum config reading cycle: 300 seconds */ + if (time_after(jiffies, data->last_updated_config + (HZ * 300)) + || !data->valid) { + + for (i = 0; i < 6; i++) { + data->in_min[i] = i2c_smbus_read_byte_data(client, + ADM9240_REG_IN_MIN(i)); + data->in_max[i] = i2c_smbus_read_byte_data(client, + ADM9240_REG_IN_MAX(i)); + } + for (i = 0; i < 2; i++) { + data->fan_min[i] = i2c_smbus_read_byte_data(client, + ADM9240_REG_FAN_MIN(i)); + } + data->temp_max[0] = i2c_smbus_read_byte_data(client, + ADM9240_REG_TEMP_MAX(0)); + data->temp_max[1] = i2c_smbus_read_byte_data(client, + ADM9240_REG_TEMP_MAX(1)); + + /* read fan divs and 5-bit VID */ + i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV); + data->fan_div[0] = (i >> 4) & 3; + data->fan_div[1] = (i >> 6) & 3; + data->vid = i & 0x0f; + data->vid |= (i2c_smbus_read_byte_data(client, + ADM9240_REG_VID4) & 1) << 4; + /* read analog out */ + data->aout = i2c_smbus_read_byte_data(client, + ADM9240_REG_ANALOG_OUT); + + data->last_updated_config = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} + /*** sysfs accessors ***/ /* temperature */ @@ -203,8 +278,8 @@ static ssize_t set_max(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -259,8 +334,8 @@ static ssize_t set_in_min(struct device *dev, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -281,8 +356,8 @@ static ssize_t set_in_max(struct device *dev, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -340,22 +415,6 @@ static ssize_t show_fan_div(struct device *dev, return sprintf(buf, "%d\n", 1 << data->fan_div[attr->index]); } -/* write new fan div, callers must hold data->update_lock */ -static void adm9240_write_fan_div(struct i2c_client *client, int nr, - u8 fan_div) -{ - u8 reg, old, shift = (nr + 2) * 2; - - reg = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV); - old = (reg >> shift) & 3; - reg &= ~(3 << shift); - reg |= (fan_div << shift); - i2c_smbus_write_byte_data(client, ADM9240_REG_VID_FAN_DIV, reg); - dev_dbg(&client->dev, - "fan%d clock divider changed from %u to %u\n", - nr + 1, 1 << old, 1 << fan_div); -} - /* * set fan speed low limit: * @@ -372,8 +431,8 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = attr->index; u8 new_div; unsigned long val; @@ -485,8 +544,8 @@ static ssize_t set_aout(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -506,8 +565,8 @@ static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); + struct adm9240_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; if (kstrtoul(buf, 10, &val) || val != 0) @@ -524,7 +583,7 @@ static ssize_t chassis_clear(struct device *dev, static SENSOR_DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, show_alarm, chassis_clear, 12); -static struct attribute *adm9240_attributes[] = { +static struct attribute *adm9240_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, @@ -568,9 +627,7 @@ static struct attribute *adm9240_attributes[] = { NULL }; -static const struct attribute_group adm9240_group = { - .attrs = adm9240_attributes, -}; +ATTRIBUTE_GROUPS(adm9240); /*** sensor chip detect and driver install ***/ @@ -620,49 +677,6 @@ static int adm9240_detect(struct i2c_client *new_client, return 0; } -static int adm9240_probe(struct i2c_client *new_client, - const struct i2c_device_id *id) -{ - struct adm9240_data *data; - int err; - - data = devm_kzalloc(&new_client->dev, sizeof(*data), GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(new_client, data); - mutex_init(&data->update_lock); - - adm9240_init_client(new_client); - - /* populate sysfs filesystem */ - err = sysfs_create_group(&new_client->dev.kobj, &adm9240_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&new_client->dev.kobj, &adm9240_group); - return err; -} - -static int adm9240_remove(struct i2c_client *client) -{ - struct adm9240_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adm9240_group); - - return 0; -} - static void adm9240_init_client(struct i2c_client *client) { struct adm9240_data *data = i2c_get_clientdata(client); @@ -705,93 +719,48 @@ static void adm9240_init_client(struct i2c_client *client) } } -static struct adm9240_data *adm9240_update_device(struct device *dev) +static int adm9240_probe(struct i2c_client *new_client, + const struct i2c_device_id *id) { - struct i2c_client *client = to_i2c_client(dev); - struct adm9240_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - /* minimum measurement cycle: 1.75 seconds */ - if (time_after(jiffies, data->last_updated_measure + (HZ * 7 / 4)) - || !data->valid) { - - for (i = 0; i < 6; i++) { /* read voltages */ - data->in[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_IN(i)); - } - data->alarms = i2c_smbus_read_byte_data(client, - ADM9240_REG_INT(0)) | - i2c_smbus_read_byte_data(client, - ADM9240_REG_INT(1)) << 8; - - /* - * read temperature: assume temperature changes less than - * 0.5'C per two measurement cycles thus ignore possible - * but unlikely aliasing error on lsb reading. --Grant - */ - data->temp = ((i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP) << 8) | - i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP_CONF)) / 128; - - for (i = 0; i < 2; i++) { /* read fans */ - data->fan[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_FAN(i)); - - /* adjust fan clock divider on overflow */ - if (data->valid && data->fan[i] == 255 && - data->fan_div[i] < 3) { + struct device *dev = &new_client->dev; + struct device *hwmon_dev; + struct adm9240_data *data; - adm9240_write_fan_div(client, i, - ++data->fan_div[i]); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; - /* adjust fan_min if active, but not to 0 */ - if (data->fan_min[i] < 255 && - data->fan_min[i] >= 2) - data->fan_min[i] /= 2; - } - } - data->last_updated_measure = jiffies; - } + i2c_set_clientdata(new_client, data); + data->client = new_client; + mutex_init(&data->update_lock); - /* minimum config reading cycle: 300 seconds */ - if (time_after(jiffies, data->last_updated_config + (HZ * 300)) - || !data->valid) { + adm9240_init_client(new_client); - for (i = 0; i < 6; i++) { - data->in_min[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_IN_MIN(i)); - data->in_max[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_IN_MAX(i)); - } - for (i = 0; i < 2; i++) { - data->fan_min[i] = i2c_smbus_read_byte_data(client, - ADM9240_REG_FAN_MIN(i)); - } - data->temp_max[0] = i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP_MAX(0)); - data->temp_max[1] = i2c_smbus_read_byte_data(client, - ADM9240_REG_TEMP_MAX(1)); + hwmon_dev = devm_hwmon_device_register_with_groups(dev, + new_client->name, + data, + adm9240_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - /* read fan divs and 5-bit VID */ - i = i2c_smbus_read_byte_data(client, ADM9240_REG_VID_FAN_DIV); - data->fan_div[0] = (i >> 4) & 3; - data->fan_div[1] = (i >> 6) & 3; - data->vid = i & 0x0f; - data->vid |= (i2c_smbus_read_byte_data(client, - ADM9240_REG_VID4) & 1) << 4; - /* read analog out */ - data->aout = i2c_smbus_read_byte_data(client, - ADM9240_REG_ANALOG_OUT); +static const struct i2c_device_id adm9240_id[] = { + { "adm9240", adm9240 }, + { "ds1780", ds1780 }, + { "lm81", lm81 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adm9240_id); - data->last_updated_config = jiffies; - data->valid = 1; - } - mutex_unlock(&data->update_lock); - return data; -} +static struct i2c_driver adm9240_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adm9240", + }, + .probe = adm9240_probe, + .id_table = adm9240_id, + .detect = adm9240_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adm9240_driver); diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 7f9dc2f86b63..22e0c926989d 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -198,7 +198,7 @@ static int ads1015_get_channels_config_of(struct i2c_client *client) } channel = be32_to_cpup(property); - if (channel > ADS1015_CHANNELS) { + if (channel >= ADS1015_CHANNELS) { dev_err(&client->dev, "invalid channel index %d on %s\n", channel, node->full_name); diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index 7092c78f814f..a622d40eec17 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -50,7 +50,7 @@ enum ads7828_chips { ads7828, ads7830 }; /* Client specific data */ struct ads7828_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; /* Mutex protecting updates */ unsigned long last_updated; /* Last updated time (in jiffies) */ u16 adc_input[ADS7828_NCH]; /* ADS7828_NCH samples */ @@ -72,8 +72,8 @@ static inline u8 ads7828_cmd_byte(u8 cmd, int ch) /* Update data for the device (all 8 channels) */ static struct ads7828_data *ads7828_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct ads7828_data *data = i2c_get_clientdata(client); + struct ads7828_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; mutex_lock(&data->update_lock); @@ -116,7 +116,7 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, ads7828_show_in, NULL, 5); static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, ads7828_show_in, NULL, 6); static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, ads7828_show_in, NULL, 7); -static struct attribute *ads7828_attributes[] = { +static struct attribute *ads7828_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, @@ -128,29 +128,17 @@ static struct attribute *ads7828_attributes[] = { NULL }; -static const struct attribute_group ads7828_group = { - .attrs = ads7828_attributes, -}; - -static int ads7828_remove(struct i2c_client *client) -{ - struct ads7828_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ads7828_group); - - return 0; -} +ATTRIBUTE_GROUPS(ads7828); static int ads7828_probe(struct i2c_client *client, const struct i2c_device_id *id) { - struct ads7828_platform_data *pdata = dev_get_platdata(&client->dev); + struct device *dev = &client->dev; + struct ads7828_platform_data *pdata = dev_get_platdata(dev); struct ads7828_data *data; - int err; + struct device *hwmon_dev; - data = devm_kzalloc(&client->dev, sizeof(struct ads7828_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct ads7828_data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -182,24 +170,13 @@ static int ads7828_probe(struct i2c_client *client, if (!data->diff_input) data->cmd_byte |= ADS7828_CMD_SD_SE; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); - err = sysfs_create_group(&client->dev.kobj, &ads7828_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error; - } - - return 0; - -error: - sysfs_remove_group(&client->dev.kobj, &ads7828_group); - return err; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + ads7828_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id ads7828_device_ids[] = { @@ -216,7 +193,6 @@ static struct i2c_driver ads7828_driver = { .id_table = ads7828_device_ids, .probe = ads7828_probe, - .remove = ads7828_remove, }; module_i2c_driver(ads7828_driver); diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c index d9299dee37d1..827c03703128 100644 --- a/drivers/hwmon/adt7411.c +++ b/drivers/hwmon/adt7411.c @@ -51,7 +51,7 @@ struct adt7411_data { struct mutex update_lock; unsigned long next_update; int vref_cached; - struct device *hwmon_dev; + struct i2c_client *client; }; /* @@ -111,7 +111,8 @@ static int adt7411_modify_bit(struct i2c_client *client, u8 reg, u8 bit, static ssize_t adt7411_show_vdd(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); + struct adt7411_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int ret = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, ADT7411_REG_VDD_MSB, 2); @@ -121,7 +122,8 @@ static ssize_t adt7411_show_vdd(struct device *dev, static ssize_t adt7411_show_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); + struct adt7411_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, ADT7411_REG_INT_TEMP_MSB, 0); @@ -137,8 +139,8 @@ static ssize_t adt7411_show_input(struct device *dev, struct device_attribute *attr, char *buf) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct adt7411_data *data = i2c_get_clientdata(client); + struct adt7411_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int val; u8 lsb_reg, lsb_shift; @@ -180,7 +182,8 @@ static ssize_t adt7411_show_bit(struct device *dev, struct device_attribute *attr, char *buf) { struct sensor_device_attribute_2 *attr2 = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); + struct adt7411_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int ret = i2c_smbus_read_byte_data(client, attr2->index); return ret < 0 ? ret : sprintf(buf, "%u\n", !!(ret & attr2->nr)); @@ -191,8 +194,8 @@ static ssize_t adt7411_set_bit(struct device *dev, size_t count) { struct sensor_device_attribute_2 *s_attr2 = to_sensor_dev_attr_2(attr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7411_data *data = i2c_get_clientdata(client); + struct adt7411_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int ret; unsigned long flag; @@ -245,9 +248,7 @@ static struct attribute *adt7411_attrs[] = { NULL }; -static const struct attribute_group adt7411_attr_grp = { - .attrs = adt7411_attrs, -}; +ATTRIBUTE_GROUPS(adt7411); static int adt7411_detect(struct i2c_client *client, struct i2c_board_info *info) @@ -281,14 +282,17 @@ static int adt7411_detect(struct i2c_client *client, static int adt7411_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct adt7411_data *data; + struct device *hwmon_dev; int ret; - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->device_lock); mutex_init(&data->update_lock); @@ -300,32 +304,10 @@ static int adt7411_probe(struct i2c_client *client, /* force update on first occasion */ data->next_update = jiffies; - ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp); - if (ret) - return ret; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - dev_info(&client->dev, "successfully registered\n"); - - return 0; - - exit_remove: - sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - return ret; -} - -static int adt7411_remove(struct i2c_client *client) -{ - struct adt7411_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + adt7411_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id adt7411_id[] = { @@ -339,7 +321,6 @@ static struct i2c_driver adt7411_driver = { .name = "adt7411", }, .probe = adt7411_probe, - .remove = adt7411_remove, .id_table = adt7411_id, .detect = adt7411_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 562cc3881d33..5929e126da63 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -202,8 +202,7 @@ static const unsigned short normal_i2c[] = { 0x58, 0x5C, I2C_CLIENT_END }; (((value) & prefix##_MASK) >> prefix##_SHIFT) struct adt7462_data { - struct device *hwmon_dev; - struct attribute_group attrs; + struct i2c_client *client; struct mutex lock; char sensors_valid; char limits_valid; @@ -232,30 +231,6 @@ struct adt7462_data { u8 alarms[ADT7462_ALARM_REG_COUNT]; }; -static int adt7462_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adt7462_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adt7462_remove(struct i2c_client *client); - -static const struct i2c_device_id adt7462_id[] = { - { "adt7462", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7462_id); - -static struct i2c_driver adt7462_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adt7462", - }, - .probe = adt7462_probe, - .remove = adt7462_remove, - .id_table = adt7462_id, - .detect = adt7462_detect, - .address_list = normal_i2c, -}; - /* * 16-bit registers on the ADT7462 are low-byte first. The data sheet says * that the low byte must be read before the high byte. @@ -705,8 +680,8 @@ static int find_trange_value(int trange) static struct adt7462_data *adt7462_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long local_jiffies = jiffies; int i; @@ -828,8 +803,8 @@ static ssize_t set_temp_min(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) @@ -866,8 +841,8 @@ static ssize_t set_temp_max(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp) || !temp_enabled(data, attr->index)) @@ -929,8 +904,8 @@ static ssize_t set_volt_max(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int x = voltage_multiplier(data, attr->index); long temp; @@ -971,8 +946,8 @@ static ssize_t set_volt_min(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int x = voltage_multiplier(data, attr->index); long temp; @@ -1061,8 +1036,8 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp) || !temp || @@ -1109,8 +1084,8 @@ static ssize_t set_force_pwm_max(struct device *dev, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; u8 reg; @@ -1142,8 +1117,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1172,8 +1147,8 @@ static ssize_t set_pwm_max(struct device *dev, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1204,8 +1179,8 @@ static ssize_t set_pwm_min(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1238,8 +1213,8 @@ static ssize_t set_pwm_hyst(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1283,8 +1258,8 @@ static ssize_t set_pwm_tmax(struct device *dev, { int temp; struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int tmin, trange_value; long trange; @@ -1324,8 +1299,8 @@ static ssize_t set_pwm_tmin(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1381,8 +1356,8 @@ static ssize_t set_pwm_auto(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1440,8 +1415,8 @@ static ssize_t set_pwm_auto_temp(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7462_data *data = i2c_get_clientdata(client); + struct adt7462_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -1725,7 +1700,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_attrs[] = { &sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr, @@ -1896,6 +1871,8 @@ static struct attribute *adt7462_attr[] = { NULL }; +ATTRIBUTE_GROUPS(adt7462); + /* Return 0 if detection is successful, -ENODEV otherwise */ static int adt7462_detect(struct i2c_client *client, struct i2c_board_info *info) @@ -1926,46 +1903,41 @@ static int adt7462_detect(struct i2c_client *client, static int adt7462_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct adt7462_data *data; - int err; + struct device *hwmon_dev; - data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct adt7462_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->lock); dev_info(&client->dev, "%s chip found\n", client->name); - /* Register sysfs hooks */ - data->attrs.attrs = adt7462_attr; - err = sysfs_create_group(&client->dev.kobj, &data->attrs); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &data->attrs); - return err; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + adt7462_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static int adt7462_remove(struct i2c_client *client) -{ - struct adt7462_data *data = i2c_get_clientdata(client); +static const struct i2c_device_id adt7462_id[] = { + { "adt7462", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adt7462_id); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->attrs); - return 0; -} +static struct i2c_driver adt7462_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adt7462", + }, + .probe = adt7462_probe, + .id_table = adt7462_id, + .detect = adt7462_detect, + .address_list = normal_i2c, +}; module_i2c_driver(adt7462_driver); diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 9ee3913850d6..f5da39a68929 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -143,8 +143,7 @@ static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) struct adt7470_data { - struct device *hwmon_dev; - struct attribute_group attrs; + struct i2c_client *client; struct mutex lock; char sensors_valid; char limits_valid; @@ -175,30 +174,6 @@ struct adt7470_data { unsigned int auto_update_interval; }; -static int adt7470_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int adt7470_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int adt7470_remove(struct i2c_client *client); - -static const struct i2c_device_id adt7470_id[] = { - { "adt7470", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, adt7470_id); - -static struct i2c_driver adt7470_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "adt7470", - }, - .probe = adt7470_probe, - .remove = adt7470_remove, - .id_table = adt7470_id, - .detect = adt7470_detect, - .address_list = normal_i2c, -}; - /* * 16-bit registers on the ADT7470 are low-byte first. The data sheet says * that the low byte must be read before the high byte. @@ -218,18 +193,6 @@ static inline int adt7470_write_word_data(struct i2c_client *client, u8 reg, || i2c_smbus_write_byte_data(client, reg + 1, value >> 8); } -static void adt7470_init_client(struct i2c_client *client) -{ - int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); - - if (reg < 0) { - dev_err(&client->dev, "cannot read configuration register\n"); - } else { - /* start monitoring (and do a self-test) */ - i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3); - } -} - /* Probe for temperature sensors. Assumes lock is held */ static int adt7470_read_temperatures(struct i2c_client *client, struct adt7470_data *data) @@ -314,8 +277,8 @@ static int adt7470_update_thread(void *p) static struct adt7470_data *adt7470_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long local_jiffies = jiffies; u8 cfg; int i; @@ -445,8 +408,7 @@ static ssize_t set_auto_update_interval(struct device *dev, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); long temp; if (kstrtol(buf, 10, &temp)) @@ -474,8 +436,7 @@ static ssize_t set_num_temp_sensors(struct device *dev, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); long temp; if (kstrtol(buf, 10, &temp)) @@ -507,8 +468,8 @@ static ssize_t set_temp_min(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -541,8 +502,8 @@ static ssize_t set_temp_max(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -596,8 +557,8 @@ static ssize_t set_fan_max(struct device *dev, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp) || !temp) @@ -633,8 +594,8 @@ static ssize_t set_fan_min(struct device *dev, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp) || !temp) @@ -677,8 +638,8 @@ static ssize_t set_force_pwm_max(struct device *dev, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; u8 reg; @@ -710,8 +671,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -742,8 +703,8 @@ static ssize_t set_pwm_max(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -775,8 +736,8 @@ static ssize_t set_pwm_min(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -818,8 +779,8 @@ static ssize_t set_pwm_tmin(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long temp; if (kstrtol(buf, 10, &temp)) @@ -852,8 +813,8 @@ static ssize_t set_pwm_auto(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int pwm_auto_reg = ADT7470_REG_PWM_CFG(attr->index); int pwm_auto_reg_mask; long temp; @@ -913,8 +874,8 @@ static ssize_t set_pwm_auto_temp(struct device *dev, size_t count) { struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct i2c_client *client = to_i2c_client(dev); - struct adt7470_data *data = i2c_get_clientdata(client); + struct adt7470_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int pwm_auto_reg = ADT7470_REG_PWM_AUTO_TEMP(attr->index); long temp; u8 reg; @@ -1131,7 +1092,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_attrs[] = { &dev_attr_alarm_mask.attr, &dev_attr_num_temp_sensors.attr, &dev_attr_auto_update_interval.attr, @@ -1223,6 +1184,8 @@ static struct attribute *adt7470_attr[] = { NULL }; +ATTRIBUTE_GROUPS(adt7470); + /* Return 0 if detection is successful, -ENODEV otherwise */ static int adt7470_detect(struct i2c_client *client, struct i2c_board_info *info) @@ -1250,14 +1213,26 @@ static int adt7470_detect(struct i2c_client *client, return 0; } +static void adt7470_init_client(struct i2c_client *client) +{ + int reg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); + + if (reg < 0) { + dev_err(&client->dev, "cannot read configuration register\n"); + } else { + /* start monitoring (and do a self-test) */ + i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, reg | 3); + } +} + static int adt7470_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct adt7470_data *data; - int err; + struct device *hwmon_dev; - data = devm_kzalloc(&client->dev, sizeof(struct adt7470_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct adt7470_data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1265,6 +1240,7 @@ static int adt7470_probe(struct i2c_client *client, data->auto_update_interval = AUTO_UPDATE_INTERVAL; i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->lock); dev_info(&client->dev, "%s chip found\n", client->name); @@ -1273,32 +1249,21 @@ static int adt7470_probe(struct i2c_client *client, adt7470_init_client(client); /* Register sysfs hooks */ - data->attrs.attrs = adt7470_attr; - err = sysfs_create_group(&client->dev.kobj, &data->attrs); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + adt7470_groups); + + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); init_completion(&data->auto_update_stop); data->auto_update = kthread_run(adt7470_update_thread, client, "%s", - dev_name(data->hwmon_dev)); + dev_name(hwmon_dev)); if (IS_ERR(data->auto_update)) { - err = PTR_ERR(data->auto_update); - goto exit_unregister; + return PTR_ERR(data->auto_update); } return 0; - -exit_unregister: - hwmon_device_unregister(data->hwmon_dev); -exit_remove: - sysfs_remove_group(&client->dev.kobj, &data->attrs); - return err; } static int adt7470_remove(struct i2c_client *client) @@ -1307,11 +1272,27 @@ static int adt7470_remove(struct i2c_client *client) kthread_stop(data->auto_update); wait_for_completion(&data->auto_update_stop); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &data->attrs); return 0; } +static const struct i2c_device_id adt7470_id[] = { + { "adt7470", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, adt7470_id); + +static struct i2c_driver adt7470_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adt7470", + }, + .probe = adt7470_probe, + .remove = adt7470_remove, + .id_table = adt7470_id, + .detect = adt7470_detect, + .address_list = normal_i2c, +}; + module_i2c_driver(adt7470_driver); MODULE_AUTHOR("Darrick J. Wong <darrick.wong@oracle.com>"); diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index 9f2be3dd28f3..12e851a5af48 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c @@ -21,7 +21,6 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - #include <linux/kernel.h> /* Needed for KERN_INFO */ #include <linux/module.h> #include <linux/init.h> @@ -33,7 +32,6 @@ #include <linux/err.h> #include <linux/mutex.h> - /* * Addresses to scan. */ @@ -41,8 +39,6 @@ static const unsigned short normal_i2c[] = {0x18, 0x19, 0x1a, 0x2c, 0x2d, 0x2e, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END}; - - /* * Insmod parameters */ @@ -53,7 +49,6 @@ module_param(pwminv, int, S_IRUGO); static int init = 1; /*Power-on initialization.*/ module_param(init, int, S_IRUGO); - enum chips { amc6821 }; #define AMC6821_REG_DEV_ID 0x3D @@ -152,46 +147,12 @@ static const u8 fan_reg_hi[] = {AMC6821_REG_TDATA_HI, AMC6821_REG_TACH_LLIMITH, AMC6821_REG_TACH_HLIMITH, }; -static int amc6821_probe( - struct i2c_client *client, - const struct i2c_device_id *id); -static int amc6821_detect( - struct i2c_client *client, - struct i2c_board_info *info); -static int amc6821_init_client(struct i2c_client *client); -static int amc6821_remove(struct i2c_client *client); -static struct amc6821_data *amc6821_update_device(struct device *dev); - -/* - * Driver data (common to all clients) - */ - -static const struct i2c_device_id amc6821_id[] = { - { "amc6821", amc6821 }, - { } -}; - -MODULE_DEVICE_TABLE(i2c, amc6821_id); - -static struct i2c_driver amc6821_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "amc6821", - }, - .probe = amc6821_probe, - .remove = amc6821_remove, - .id_table = amc6821_id, - .detect = amc6821_detect, - .address_list = normal_i2c, -}; - - /* * Client data (each client gets its own) */ struct amc6821_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -213,6 +174,108 @@ struct amc6821_data { u8 stat2; }; +static struct amc6821_data *amc6821_update_device(struct device *dev) +{ + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int timeout = HZ; + u8 reg; + int i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + timeout) || + !data->valid) { + + for (i = 0; i < TEMP_IDX_LEN; i++) + data->temp[i] = i2c_smbus_read_byte_data(client, + temp_reg[i]); + + data->stat1 = i2c_smbus_read_byte_data(client, + AMC6821_REG_STAT1); + data->stat2 = i2c_smbus_read_byte_data(client, + AMC6821_REG_STAT2); + + data->pwm1 = i2c_smbus_read_byte_data(client, + AMC6821_REG_DCY); + for (i = 0; i < FAN1_IDX_LEN; i++) { + data->fan[i] = i2c_smbus_read_byte_data( + client, + fan_reg_low[i]); + data->fan[i] += i2c_smbus_read_byte_data( + client, + fan_reg_hi[i]) << 8; + } + data->fan1_div = i2c_smbus_read_byte_data(client, + AMC6821_REG_CONF4); + data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; + + data->pwm1_auto_point_pwm[0] = 0; + data->pwm1_auto_point_pwm[2] = 255; + data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, + AMC6821_REG_DCY_LOW_TEMP); + + data->temp1_auto_point_temp[0] = + i2c_smbus_read_byte_data(client, + AMC6821_REG_PSV_TEMP); + data->temp2_auto_point_temp[0] = + data->temp1_auto_point_temp[0]; + reg = i2c_smbus_read_byte_data(client, + AMC6821_REG_LTEMP_FAN_CTRL); + data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; + reg &= 0x07; + reg = 0x20 >> reg; + if (reg > 0) + data->temp1_auto_point_temp[2] = + data->temp1_auto_point_temp[1] + + (data->pwm1_auto_point_pwm[2] - + data->pwm1_auto_point_pwm[1]) / reg; + else + data->temp1_auto_point_temp[2] = 255; + + reg = i2c_smbus_read_byte_data(client, + AMC6821_REG_RTEMP_FAN_CTRL); + data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; + reg &= 0x07; + reg = 0x20 >> reg; + if (reg > 0) + data->temp2_auto_point_temp[2] = + data->temp2_auto_point_temp[1] + + (data->pwm1_auto_point_pwm[2] - + data->pwm1_auto_point_pwm[1]) / reg; + else + data->temp2_auto_point_temp[2] = 255; + + reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); + reg = (reg >> 5) & 0x3; + switch (reg) { + case 0: /*open loop: software sets pwm1*/ + data->pwm1_auto_channels_temp = 0; + data->pwm1_enable = 1; + break; + case 2: /*closed loop: remote T (temp2)*/ + data->pwm1_auto_channels_temp = 2; + data->pwm1_enable = 2; + break; + case 3: /*closed loop: local and remote T (temp2)*/ + data->pwm1_auto_channels_temp = 3; + data->pwm1_enable = 3; + break; + case 1: /* + * semi-open loop: software sets rpm, chip controls + * pwm1, currently not implemented + */ + data->pwm1_auto_channels_temp = 0; + data->pwm1_enable = 0; + break; + } + + data->last_updated = jiffies; + data->valid = 1; + } + mutex_unlock(&data->update_lock); + return data; +} static ssize_t get_temp( struct device *dev, @@ -225,16 +288,14 @@ static ssize_t get_temp( return sprintf(buf, "%d\n", data->temp[ix] * 1000); } - - static ssize_t set_temp( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int ix = to_sensor_dev_attr(attr)->index; long val; @@ -253,9 +314,6 @@ static ssize_t set_temp( return count; } - - - static ssize_t get_temp_alarm( struct device *dev, struct device_attribute *devattr, @@ -294,9 +352,6 @@ static ssize_t get_temp_alarm( return sprintf(buf, "0"); } - - - static ssize_t get_temp2_fault( struct device *dev, struct device_attribute *devattr, @@ -324,8 +379,8 @@ static ssize_t set_pwm1( const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int ret = kstrtol(buf, 10, &val); if (ret) @@ -353,18 +408,20 @@ static ssize_t set_pwm1_enable( const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int config = kstrtol(buf, 10, &val); if (config) return config; + mutex_lock(&data->update_lock); config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); if (config < 0) { dev_err(&client->dev, "Error reading configuration register, aborting.\n"); - return config; + count = config; + goto unlock; } switch (val) { @@ -381,19 +438,19 @@ static ssize_t set_pwm1_enable( config |= AMC6821_CONF1_FDRC1; break; default: - return -EINVAL; + count = -EINVAL; + goto unlock; } - mutex_lock(&data->update_lock); if (i2c_smbus_write_byte_data(client, AMC6821_REG_CONF1, config)) { dev_err(&client->dev, "Configuration register write error, aborting.\n"); count = -EIO; } +unlock: mutex_unlock(&data->update_lock); return count; } - static ssize_t get_pwm1_auto_channels_temp( struct device *dev, struct device_attribute *devattr, @@ -403,7 +460,6 @@ static ssize_t get_pwm1_auto_channels_temp( return sprintf(buf, "%d\n", data->pwm1_auto_channels_temp); } - static ssize_t get_temp_auto_point_temp( struct device *dev, struct device_attribute *devattr, @@ -425,7 +481,6 @@ static ssize_t get_temp_auto_point_temp( } } - static ssize_t get_pwm1_auto_point_pwm( struct device *dev, struct device_attribute *devattr, @@ -436,7 +491,6 @@ static ssize_t get_pwm1_auto_point_pwm( return sprintf(buf, "%d\n", data->pwm1_auto_point_pwm[ix]); } - static inline ssize_t set_slope_register(struct i2c_client *client, u8 reg, u8 dpwm, @@ -459,16 +513,14 @@ static inline ssize_t set_slope_register(struct i2c_client *client, return 0; } - - static ssize_t set_temp_auto_point_temp( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); struct amc6821_data *data = amc6821_update_device(dev); + struct i2c_client *client = data->client; int ix = to_sensor_dev_attr_2(attr)->index; int nr = to_sensor_dev_attr_2(attr)->nr; u8 *ptemp; @@ -493,8 +545,9 @@ static ssize_t set_temp_auto_point_temp( return -EINVAL; } - data->valid = 0; mutex_lock(&data->update_lock); + data->valid = 0; + switch (ix) { case 0: ptemp[0] = clamp_val(val / 1000, 0, @@ -533,16 +586,14 @@ EXIT: return count; } - - static ssize_t set_pwm1_auto_point_pwm( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int dpwm; long val; int ret = kstrtol(buf, 10, &val); @@ -587,8 +638,6 @@ static ssize_t get_fan( return sprintf(buf, "%d\n", (int)(6000000 / data->fan[ix])); } - - static ssize_t get_fan1_fault( struct device *dev, struct device_attribute *devattr, @@ -601,15 +650,13 @@ static ssize_t get_fan1_fault( return sprintf(buf, "0"); } - - static ssize_t set_fan( struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int ix = to_sensor_dev_attr(attr)->index; int ret = kstrtol(buf, 10, &val); @@ -635,8 +682,6 @@ EXIT: return count; } - - static ssize_t get_fan1_div( struct device *dev, struct device_attribute *devattr, @@ -651,20 +696,21 @@ static ssize_t set_fan1_div( struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); + struct amc6821_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int config = kstrtol(buf, 10, &val); if (config) return config; + mutex_lock(&data->update_lock); config = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF4); if (config < 0) { dev_err(&client->dev, "Error reading configuration register, aborting.\n"); - return config; + count = config; + goto EXIT; } - mutex_lock(&data->update_lock); switch (val) { case 2: config &= ~AMC6821_CONF4_PSPR; @@ -688,8 +734,6 @@ EXIT: return count; } - - static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, get_temp, NULL, IDX_TEMP1_INPUT); static SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO | S_IWUSR, get_temp, @@ -754,8 +798,6 @@ static SENSOR_DEVICE_ATTR_2(temp2_auto_point2_temp, S_IWUSR | S_IRUGO, static SENSOR_DEVICE_ATTR_2(temp2_auto_point3_temp, S_IWUSR | S_IRUGO, get_temp_auto_point_temp, set_temp_auto_point_temp, 2, 2); - - static struct attribute *amc6821_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, @@ -792,11 +834,7 @@ static struct attribute *amc6821_attrs[] = { NULL }; -static struct attribute_group amc6821_attr_grp = { - .attrs = amc6821_attrs, -}; - - +ATTRIBUTE_GROUPS(amc6821); /* Return 0 if detection is successful, -ENODEV otherwise */ static int amc6821_detect( @@ -844,53 +882,6 @@ static int amc6821_detect( return 0; } -static int amc6821_probe( - struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct amc6821_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct amc6821_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* - * Initialize the amc6821 chip - */ - err = amc6821_init_client(client); - if (err) - return err; - - err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; - - err = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "error registering hwmon device.\n"); - sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); - return err; -} - -static int amc6821_remove(struct i2c_client *client) -{ - struct amc6821_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); - - return 0; -} - - static int amc6821_init_client(struct i2c_client *client) { int config; @@ -977,109 +968,51 @@ static int amc6821_init_client(struct i2c_client *client) return 0; } - -static struct amc6821_data *amc6821_update_device(struct device *dev) +static int amc6821_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client = to_i2c_client(dev); - struct amc6821_data *data = i2c_get_clientdata(client); - int timeout = HZ; - u8 reg; - int i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + timeout) || - !data->valid) { - - for (i = 0; i < TEMP_IDX_LEN; i++) - data->temp[i] = i2c_smbus_read_byte_data(client, - temp_reg[i]); + struct device *dev = &client->dev; + struct amc6821_data *data; + struct device *hwmon_dev; + int err; - data->stat1 = i2c_smbus_read_byte_data(client, - AMC6821_REG_STAT1); - data->stat2 = i2c_smbus_read_byte_data(client, - AMC6821_REG_STAT2); + data = devm_kzalloc(dev, sizeof(struct amc6821_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - data->pwm1 = i2c_smbus_read_byte_data(client, - AMC6821_REG_DCY); - for (i = 0; i < FAN1_IDX_LEN; i++) { - data->fan[i] = i2c_smbus_read_byte_data( - client, - fan_reg_low[i]); - data->fan[i] += i2c_smbus_read_byte_data( - client, - fan_reg_hi[i]) << 8; - } - data->fan1_div = i2c_smbus_read_byte_data(client, - AMC6821_REG_CONF4); - data->fan1_div = data->fan1_div & AMC6821_CONF4_PSPR ? 4 : 2; + data->client = client; + mutex_init(&data->update_lock); - data->pwm1_auto_point_pwm[0] = 0; - data->pwm1_auto_point_pwm[2] = 255; - data->pwm1_auto_point_pwm[1] = i2c_smbus_read_byte_data(client, - AMC6821_REG_DCY_LOW_TEMP); + /* + * Initialize the amc6821 chip + */ + err = amc6821_init_client(client); + if (err) + return err; - data->temp1_auto_point_temp[0] = - i2c_smbus_read_byte_data(client, - AMC6821_REG_PSV_TEMP); - data->temp2_auto_point_temp[0] = - data->temp1_auto_point_temp[0]; - reg = i2c_smbus_read_byte_data(client, - AMC6821_REG_LTEMP_FAN_CTRL); - data->temp1_auto_point_temp[1] = (reg & 0xF8) >> 1; - reg &= 0x07; - reg = 0x20 >> reg; - if (reg > 0) - data->temp1_auto_point_temp[2] = - data->temp1_auto_point_temp[1] + - (data->pwm1_auto_point_pwm[2] - - data->pwm1_auto_point_pwm[1]) / reg; - else - data->temp1_auto_point_temp[2] = 255; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + amc6821_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - reg = i2c_smbus_read_byte_data(client, - AMC6821_REG_RTEMP_FAN_CTRL); - data->temp2_auto_point_temp[1] = (reg & 0xF8) >> 1; - reg &= 0x07; - reg = 0x20 >> reg; - if (reg > 0) - data->temp2_auto_point_temp[2] = - data->temp2_auto_point_temp[1] + - (data->pwm1_auto_point_pwm[2] - - data->pwm1_auto_point_pwm[1]) / reg; - else - data->temp2_auto_point_temp[2] = 255; +static const struct i2c_device_id amc6821_id[] = { + { "amc6821", amc6821 }, + { } +}; - reg = i2c_smbus_read_byte_data(client, AMC6821_REG_CONF1); - reg = (reg >> 5) & 0x3; - switch (reg) { - case 0: /*open loop: software sets pwm1*/ - data->pwm1_auto_channels_temp = 0; - data->pwm1_enable = 1; - break; - case 2: /*closed loop: remote T (temp2)*/ - data->pwm1_auto_channels_temp = 2; - data->pwm1_enable = 2; - break; - case 3: /*closed loop: local and remote T (temp2)*/ - data->pwm1_auto_channels_temp = 3; - data->pwm1_enable = 3; - break; - case 1: /* - * semi-open loop: software sets rpm, chip controls - * pwm1, currently not implemented - */ - data->pwm1_auto_channels_temp = 0; - data->pwm1_enable = 0; - break; - } +MODULE_DEVICE_TABLE(i2c, amc6821_id); - data->last_updated = jiffies; - data->valid = 1; - } - mutex_unlock(&data->update_lock); - return data; -} +static struct i2c_driver amc6821_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "amc6821", + }, + .probe = amc6821_probe, + .id_table = amc6821_id, + .detect = amc6821_detect, + .address_list = normal_i2c, +}; module_i2c_driver(amc6821_driver); diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 71463689d163..c77644d45a02 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c @@ -300,7 +300,7 @@ static ssize_t store_fan16(struct device *dev, * respectively. That doesn't mean that's what the motherboard provides. :) */ -static int asc7621_in_scaling[] = { +static const int asc7621_in_scaling[] = { 2500, 2250, 3300, 5000, 12000 }; @@ -451,7 +451,7 @@ static ssize_t store_temp62(struct device *dev, * hwmon specs, we synthesize the auto_point_2 from them. */ -static u32 asc7621_range_map[] = { +static const u32 asc7621_range_map[] = { 2000, 2500, 3330, 4000, 5000, 6670, 8000, 10000, 13330, 16000, 20000, 26670, 32000, 40000, 53330, 80000, }; @@ -512,7 +512,7 @@ static ssize_t show_pwm_ac(struct device *dev, { SETUP_SHOW_DATA_PARAM(dev, attr); u8 config, altbit, regval; - u8 map[] = { + const u8 map[] = { 0x01, 0x02, 0x04, 0x1f, 0x00, 0x06, 0x07, 0x10, 0x08, 0x0f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f }; @@ -533,7 +533,7 @@ static ssize_t store_pwm_ac(struct device *dev, SETUP_STORE_DATA_PARAM(dev, attr); unsigned long reqval; u8 currval, config, altbit, newval; - u16 map[] = { + const u16 map[] = { 0x04, 0x00, 0x01, 0xff, 0x02, 0xff, 0x05, 0x06, 0x08, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x07, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, @@ -651,7 +651,7 @@ static ssize_t store_pwm_enable(struct device *dev, return count; } -static u32 asc7621_pwm_freq_map[] = { +static const u32 asc7621_pwm_freq_map[] = { 10, 15, 23, 30, 38, 47, 62, 94, 23000, 24000, 25000, 26000, 27000, 28000, 29000, 30000 }; @@ -700,7 +700,7 @@ static ssize_t store_pwm_freq(struct device *dev, return count; } -static u32 asc7621_pwm_auto_spinup_map[] = { +static const u32 asc7621_pwm_auto_spinup_map[] = { 0, 100, 250, 400, 700, 1000, 2000, 4000 }; @@ -749,7 +749,7 @@ static ssize_t store_pwm_ast(struct device *dev, return count; } -static u32 asc7621_temp_smoothing_time_map[] = { +static const u32 asc7621_temp_smoothing_time_map[] = { 35000, 17600, 11800, 7000, 4400, 3000, 1600, 800 }; diff --git a/drivers/hwmon/atxp1.c b/drivers/hwmon/atxp1.c index 2ae8a304b5ef..4c829bb2f9db 100644 --- a/drivers/hwmon/atxp1.c +++ b/drivers/hwmon/atxp1.c @@ -46,7 +46,7 @@ MODULE_AUTHOR("Sebastian Witt <se.witt@gmx.net>"); static const unsigned short normal_i2c[] = { 0x37, 0x4e, I2C_CLIENT_END }; struct atxp1_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; unsigned long last_updated; u8 valid; @@ -61,11 +61,8 @@ struct atxp1_data { static struct atxp1_data *atxp1_update_device(struct device *dev) { - struct i2c_client *client; - struct atxp1_data *data; - - client = to_i2c_client(dev); - data = i2c_get_clientdata(client); + struct atxp1_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; mutex_lock(&data->update_lock); @@ -105,15 +102,12 @@ 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; + struct atxp1_data *data = atxp1_update_device(dev); + struct i2c_client *client = data->client; int vid, cvid; unsigned long vcore; int err; - client = to_i2c_client(dev); - data = atxp1_update_device(dev); - err = kstrtoul(buf, 10, &vcore); if (err) return err; @@ -184,14 +178,11 @@ 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; + struct atxp1_data *data = atxp1_update_device(dev); + struct i2c_client *client = data->client; unsigned long value; int err; - client = to_i2c_client(dev); - data = atxp1_update_device(dev); - err = kstrtoul(buf, 16, &value); if (err) return err; @@ -234,7 +225,7 @@ static ssize_t atxp1_storegpio2(struct device *dev, const char *buf, size_t count) { struct atxp1_data *data = atxp1_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client = data->client; unsigned long value; int err; @@ -260,17 +251,13 @@ static ssize_t atxp1_storegpio2(struct device *dev, */ static DEVICE_ATTR(gpio2, S_IRUGO | S_IWUSR, atxp1_showgpio2, atxp1_storegpio2); -static struct attribute *atxp1_attributes[] = { +static struct attribute *atxp1_attrs[] = { &dev_attr_gpio1.attr, &dev_attr_gpio2.attr, &dev_attr_cpu0_vid.attr, NULL }; - -static const struct attribute_group atxp1_group = { - .attrs = atxp1_attributes, -}; - +ATTRIBUTE_GROUPS(atxp1); /* Return 0 if detection is successful, -ENODEV otherwise */ static int atxp1_detect(struct i2c_client *new_client, @@ -314,50 +301,30 @@ static int atxp1_detect(struct i2c_client *new_client, return 0; } -static int atxp1_probe(struct i2c_client *new_client, +static int atxp1_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct atxp1_data *data; - int err; + struct device *hwmon_dev; - data = devm_kzalloc(&new_client->dev, sizeof(struct atxp1_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct atxp1_data), GFP_KERNEL); if (!data) return -ENOMEM; /* Get VRM */ data->vrm = vid_which_vrm(); - i2c_set_clientdata(new_client, data); + data->client = client; mutex_init(&data->update_lock); - /* Register sysfs hooks */ - err = sysfs_create_group(&new_client->dev.kobj, &atxp1_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&new_client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - dev_info(&new_client->dev, "Using VRM: %d.%d\n", - data->vrm / 10, data->vrm % 10); - - return 0; - -exit_remove_files: - sysfs_remove_group(&new_client->dev.kobj, &atxp1_group); - return err; -}; - -static int atxp1_remove(struct i2c_client *client) -{ - struct atxp1_data *data = i2c_get_clientdata(client); + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + atxp1_groups); + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &atxp1_group); + dev_info(dev, "Using VRM: %d.%d\n", data->vrm / 10, data->vrm % 10); return 0; }; @@ -374,7 +341,6 @@ static struct i2c_driver atxp1_driver = { .name = "atxp1", }, .probe = atxp1_probe, - .remove = atxp1_remove, .id_table = atxp1_id, .detect = atxp1_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 0918b9136588..edf550fc4eef 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -67,7 +67,7 @@ static const u8 DS620_REG_TEMP[3] = { /* Each client has this additional data */ struct ds620_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -106,8 +106,8 @@ static void ds620_init_client(struct i2c_client *client) static struct ds620_data *ds620_update_client(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct ds620_data *data = i2c_get_clientdata(client); + struct ds620_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; struct ds620_data *ret = data; mutex_lock(&data->update_lock); @@ -158,8 +158,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, long val; struct sensor_device_attribute *attr = to_sensor_dev_attr(da); - struct i2c_client *client = to_i2c_client(dev); - struct ds620_data *data = i2c_get_clientdata(client); + struct ds620_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; res = kstrtol(buf, 10, &val); @@ -181,13 +181,15 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *da, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct ds620_data *data = ds620_update_client(dev); - struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client; u16 conf, new_conf; int res; if (IS_ERR(data)) return PTR_ERR(data); + client = data->client; + /* reset alarms if necessary */ res = i2c_smbus_read_word_swapped(client, DS620_REG_CONF); if (res < 0) @@ -213,7 +215,7 @@ static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, DS620_REG_CONFIG_THF); -static struct attribute *ds620_attributes[] = { +static struct attribute *ds620_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_min.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr, @@ -222,55 +224,28 @@ static struct attribute *ds620_attributes[] = { NULL }; -static const struct attribute_group ds620_group = { - .attrs = ds620_attributes, -}; +ATTRIBUTE_GROUPS(ds620); static int ds620_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct ds620_data *data; - int err; - data = devm_kzalloc(&client->dev, sizeof(struct ds620_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct ds620_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); /* Initialize the DS620 chip */ ds620_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &ds620_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - dev_info(&client->dev, "temperature sensor found\n"); - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &ds620_group); - return err; -} - -static int ds620_remove(struct i2c_client *client) -{ - struct ds620_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &ds620_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, ds620_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id ds620_id[] = { @@ -287,7 +262,6 @@ static struct i2c_driver ds620_driver = { .name = "ds620", }, .probe = ds620_probe, - .remove = ds620_remove, .id_table = ds620_id, }; diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index a37b2204a418..1ea7ca510f84 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -416,7 +416,7 @@ static bool emc1403_regmap_is_volatile(struct device *dev, unsigned int reg) } } -static struct regmap_config emc1403_regmap_config = { +static const struct regmap_config emc1403_regmap_config = { .reg_bits = 8, .val_bits = 8, .cache_type = REGCACHE_RBTREE, diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index 78002de46cb6..952fe692d764 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c @@ -66,7 +66,8 @@ struct temperature { }; struct emc2103_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[4]; struct mutex update_lock; bool valid; /* registers are valid */ bool fan_rpm_control; @@ -146,8 +147,8 @@ static void read_fan_config_from_i2c(struct i2c_client *client) static struct emc2103_data *emc2103_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); + struct emc2103_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; mutex_lock(&data->update_lock); @@ -242,8 +243,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { int nr = to_sensor_dev_attr(da)->index; - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); + struct emc2103_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int result = kstrtol(buf, 10, &val); @@ -264,8 +265,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { int nr = to_sensor_dev_attr(da)->index; - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); + struct emc2103_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int result = kstrtol(buf, 10, &val); @@ -310,7 +311,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct emc2103_data *data = emc2103_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client = data->client; int new_range_bits, old_div = 8 / data->fan_multiplier; long new_div; @@ -385,7 +386,7 @@ static ssize_t set_fan_target(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { struct emc2103_data *data = emc2103_update_device(dev); - struct i2c_client *client = to_i2c_client(dev); + struct i2c_client *client = data->client; unsigned long rpm_target; int result = kstrtoul(buf, 10, &rpm_target); @@ -428,8 +429,8 @@ show_pwm_enable(struct device *dev, struct device_attribute *da, char *buf) static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct emc2103_data *data = i2c_get_clientdata(client); + struct emc2103_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long new_value; u8 conf_reg; @@ -580,7 +581,8 @@ static int emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct emc2103_data *data; - int status; + struct device *hwmon_dev; + int status, idx = 0; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; @@ -591,6 +593,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) return -ENOMEM; i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); /* 2103-2 and 2103-4 have 3 external diodes, 2103-1 has 1 */ @@ -624,60 +627,21 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) } } - /* Register sysfs hooks */ - status = sysfs_create_group(&client->dev.kobj, &emc2103_group); - if (status) - return status; - - if (data->temp_count >= 3) { - status = sysfs_create_group(&client->dev.kobj, - &emc2103_temp3_group); - if (status) - goto exit_remove; - } - - if (data->temp_count == 4) { - status = sysfs_create_group(&client->dev.kobj, - &emc2103_temp4_group); - if (status) - goto exit_remove_temp3; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - status = PTR_ERR(data->hwmon_dev); - goto exit_remove_temp4; - } - - dev_info(&client->dev, "%s: sensor '%s'\n", - dev_name(data->hwmon_dev), client->name); - - return 0; - -exit_remove_temp4: - if (data->temp_count == 4) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); -exit_remove_temp3: + /* sysfs hooks */ + data->groups[idx++] = &emc2103_group; if (data->temp_count >= 3) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); -exit_remove: - sysfs_remove_group(&client->dev.kobj, &emc2103_group); - return status; -} - -static int emc2103_remove(struct i2c_client *client) -{ - struct emc2103_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - + data->groups[idx++] = &emc2103_temp3_group; if (data->temp_count == 4) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp4_group); + data->groups[idx++] = &emc2103_temp4_group; - if (data->temp_count >= 3) - sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, + client->name, data, + data->groups); + if (IS_ERR(hwmon_dev)) + return PTR_ERR(hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &emc2103_group); + dev_info(&client->dev, "%s: sensor '%s'\n", + dev_name(hwmon_dev), client->name); return 0; } @@ -717,7 +681,6 @@ static struct i2c_driver emc2103_driver = { .name = "emc2103", }, .probe = emc2103_probe, - .remove = emc2103_remove, .id_table = emc2103_ids, .detect = emc2103_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/emc6w201.c b/drivers/hwmon/emc6w201.c index f76a74cb6dc4..e87da902f3ae 100644 --- a/drivers/hwmon/emc6w201.c +++ b/drivers/hwmon/emc6w201.c @@ -56,7 +56,7 @@ enum subfeature { input, min, max }; */ struct emc6w201_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; /* zero until following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -134,8 +134,8 @@ static int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val) static struct emc6w201_data *emc6w201_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); + struct emc6w201_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr; mutex_lock(&data->update_lock); @@ -203,8 +203,8 @@ static ssize_t show_in(struct device *dev, struct device_attribute *devattr, static ssize_t set_in(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); + struct emc6w201_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int sf = to_sensor_dev_attr_2(devattr)->index; int nr = to_sensor_dev_attr_2(devattr)->nr; int err; @@ -240,8 +240,8 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr, static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); + struct emc6w201_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int sf = to_sensor_dev_attr_2(devattr)->index; int nr = to_sensor_dev_attr_2(devattr)->nr; int err; @@ -283,8 +283,8 @@ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr, static ssize_t set_fan(struct device *dev, struct device_attribute *devattr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct emc6w201_data *data = i2c_get_clientdata(client); + struct emc6w201_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int sf = to_sensor_dev_attr_2(devattr)->index; int nr = to_sensor_dev_attr_2(devattr)->nr; int err; @@ -388,7 +388,7 @@ static SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, input); static SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan, 4, min); -static struct attribute *emc6w201_attributes[] = { +static struct attribute *emc6w201_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, @@ -440,9 +440,7 @@ static struct attribute *emc6w201_attributes[] = { NULL }; -static const struct attribute_group emc6w201_group = { - .attrs = emc6w201_attributes, -}; +ATTRIBUTE_GROUPS(emc6w201); /* * Driver interface @@ -488,44 +486,21 @@ static int emc6w201_detect(struct i2c_client *client, static int emc6w201_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct emc6w201_data *data; - int err; + struct device *hwmon_dev; - data = devm_kzalloc(&client->dev, sizeof(struct emc6w201_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct emc6w201_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); - /* Create sysfs attribute */ - err = sysfs_create_group(&client->dev.kobj, &emc6w201_group); - if (err) - return err; - - /* Expose as a hwmon device */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - - exit_remove: - sysfs_remove_group(&client->dev.kobj, &emc6w201_group); - return err; -} - -static int emc6w201_remove(struct i2c_client *client) -{ - struct emc6w201_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &emc6w201_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + emc6w201_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id emc6w201_id[] = { @@ -540,7 +515,6 @@ static struct i2c_driver emc6w201_driver = { .name = "emc6w201", }, .probe = emc6w201_probe, - .remove = emc6w201_remove, .id_table = emc6w201_id, .detect = emc6w201_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 6040121a405a..4a7cbfad1d74 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -31,9 +31,6 @@ MODULE_DESCRIPTION("AMD Family 15h CPU processor power monitor"); MODULE_AUTHOR("Andreas Herrmann <herrmann.der.user@googlemail.com>"); MODULE_LICENSE("GPL"); -/* Family 16h Northbridge's function 4 PCI ID */ -#define PCI_DEVICE_ID_AMD_16H_NB_F4 0x1534 - /* D18F3 */ #define REG_NORTHBRIDGE_CAP 0xe8 @@ -45,7 +42,7 @@ MODULE_LICENSE("GPL"); #define REG_TDP_LIMIT3 0xe8 struct fam15h_power_data { - struct device *hwmon_dev; + struct pci_dev *pdev; unsigned int tdp_to_watts; unsigned int base_tdp; unsigned int processor_pwr_watts; @@ -57,8 +54,8 @@ static ssize_t show_power(struct device *dev, u32 val, tdp_limit, running_avg_range; s32 running_avg_capture; u64 curr_pwr_watts; - struct pci_dev *f4 = to_pci_dev(dev); struct fam15h_power_data *data = dev_get_drvdata(dev); + struct pci_dev *f4 = data->pdev; pci_bus_read_config_dword(f4->bus, PCI_DEVFN(PCI_SLOT(f4->devfn), 5), REG_TDP_RUNNING_AVERAGE, &val); @@ -96,23 +93,13 @@ static ssize_t show_power_crit(struct device *dev, } static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "fam15h_power\n"); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - static struct attribute *fam15h_power_attrs[] = { &dev_attr_power1_input.attr, &dev_attr_power1_crit.attr, - &dev_attr_name.attr, NULL }; -static const struct attribute_group fam15h_power_attr_group = { - .attrs = fam15h_power_attrs, -}; +ATTRIBUTE_GROUPS(fam15h_power); static bool fam15h_power_is_internal_node0(struct pci_dev *f4) { @@ -202,7 +189,7 @@ static int fam15h_power_probe(struct pci_dev *pdev, { struct fam15h_power_data *data; struct device *dev = &pdev->dev; - int err; + struct device *hwmon_dev; /* * though we ignore every other northbridge, we still have to @@ -219,34 +206,12 @@ static int fam15h_power_probe(struct pci_dev *pdev, return -ENOMEM; fam15h_power_init_data(pdev, data); + data->pdev = pdev; - dev_set_drvdata(dev, data); - err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_group; - } - - return 0; - -exit_remove_group: - sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); - return err; -} - -static void fam15h_power_remove(struct pci_dev *pdev) -{ - struct device *dev; - struct fam15h_power_data *data; - - dev = &pdev->dev; - data = dev_get_drvdata(dev); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); + hwmon_dev = devm_hwmon_device_register_with_groups(dev, "fam15h_power", + data, + fam15h_power_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct pci_device_id fam15h_power_id_table[] = { @@ -260,7 +225,6 @@ static struct pci_driver fam15h_power_driver = { .name = "fam15h_power", .id_table = fam15h_power_id_table, .probe = fam15h_power_probe, - .remove = fam15h_power_remove, .resume = fam15h_power_resume, }; diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index ea6480b80e7f..ec6a77da411a 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c @@ -24,12 +24,6 @@ #include <linux/mutex.h> #include <linux/sysfs.h> -static const struct i2c_device_id g760a_id[] = { - { "g760a", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, g760a_id); - enum g760a_regs { G760A_REG_SET_CNT = 0x00, G760A_REG_ACT_CNT = 0x01, @@ -44,7 +38,6 @@ enum g760a_regs { struct g760a_data { struct i2c_client *client; - struct device *hwmon_dev; struct mutex update_lock; /* board specific parameters */ @@ -74,20 +67,6 @@ static inline unsigned int rpm_from_cnt(u8 val, u32 clk, u16 div) return ((val == 0x00) ? 0 : ((clk*30)/(val*div))); } -/* new-style driver model */ -static int g760a_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int g760a_remove(struct i2c_client *client); - -static struct i2c_driver g760a_driver = { - .driver = { - .name = "g760a", - }, - .probe = g760a_probe, - .remove = g760a_remove, - .id_table = g760a_id, -}; - /* read/write wrappers */ static int g760a_read_value(struct i2c_client *client, enum g760a_regs reg) { @@ -106,8 +85,8 @@ static int g760a_write_value(struct i2c_client *client, enum g760a_regs reg, static struct g760a_data *g760a_update_client(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct g760a_data *data = i2c_get_clientdata(client); + struct g760a_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; mutex_lock(&data->update_lock); @@ -163,8 +142,8 @@ static ssize_t get_pwm(struct device *dev, struct device_attribute *da, static ssize_t set_pwm(struct device *dev, struct device_attribute *da, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); struct g760a_data *data = g760a_update_client(dev); + struct i2c_client *client = data->client; unsigned long val; if (kstrtoul(buf, 10, &val)) @@ -182,16 +161,14 @@ static DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, get_pwm, set_pwm); static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL); static DEVICE_ATTR(fan1_alarm, S_IRUGO, show_fan_alarm, NULL); -static struct attribute *g760a_attributes[] = { +static struct attribute *g760a_attrs[] = { &dev_attr_pwm1.attr, &dev_attr_fan1_input.attr, &dev_attr_fan1_alarm.attr, NULL }; -static const struct attribute_group g760a_group = { - .attrs = g760a_attributes, -}; +ATTRIBUTE_GROUPS(g760a); /* * new-style driver model code @@ -200,20 +177,17 @@ static const struct attribute_group g760a_group = { static int g760a_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct g760a_data *data; - int err; + struct device *hwmon_dev; - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - data = devm_kzalloc(&client->dev, sizeof(struct g760a_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct g760a_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); - data->client = client; mutex_init(&data->update_lock); @@ -221,31 +195,25 @@ static int g760a_probe(struct i2c_client *client, data->fan_div = G760A_DEFAULT_FAN_DIV; data->clk = G760A_DEFAULT_CLK; - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &g760a_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error_hwmon_device_register; - } - - return 0; - -error_hwmon_device_register: - sysfs_remove_group(&client->dev.kobj, &g760a_group); - return err; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + g760a_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static int g760a_remove(struct i2c_client *client) -{ - struct g760a_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &g760a_group); - return 0; -} +static const struct i2c_device_id g760a_id[] = { + { "g760a", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, g760a_id); + +static struct i2c_driver g760a_driver = { + .driver = { + .name = "g760a", + }, + .probe = g760a_probe, + .id_table = g760a_id, +}; module_i2c_driver(g760a_driver); diff --git a/drivers/hwmon/g762.c b/drivers/hwmon/g762.c index 98a8618d8fbf..6aac695b1688 100644 --- a/drivers/hwmon/g762.c +++ b/drivers/hwmon/g762.c @@ -128,8 +128,8 @@ enum g762_regs { G762_REG_FAN_CMD2_GEAR_MODE_1)) >> 2)) struct g762_data { - struct i2c_client *client; struct device *hwmon_dev; + struct i2c_client *client; struct clk *clk; /* update mutex */ @@ -206,8 +206,8 @@ static inline unsigned char cnt_from_rpm(u32 rpm, u32 clk_freq, u16 p, /* helper to grab and cache data, at most one time per second */ static struct g762_data *g762_update_client(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct g762_data *data = i2c_get_clientdata(client); + struct g762_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int ret = 0; mutex_lock(&data->update_lock); @@ -266,8 +266,7 @@ static struct g762_data *g762_update_client(struct device *dev) */ static int do_set_clk_freq(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); - struct g762_data *data = i2c_get_clientdata(client); + struct g762_data *data = dev_get_drvdata(dev); if (val > 0xffffff) return -EINVAL; @@ -282,7 +281,6 @@ static int do_set_clk_freq(struct device *dev, unsigned long val) /* Set pwm mode. Accepts either 0 (PWM mode) or 1 (DC mode) */ static int do_set_pwm_mode(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -301,7 +299,7 @@ static int do_set_pwm_mode(struct device *dev, unsigned long val) ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1, data->fan_cmd1); data->valid = false; out: @@ -313,7 +311,6 @@ static int do_set_pwm_mode(struct device *dev, unsigned long val) /* Set fan clock divisor. Accepts either 1, 2, 4 or 8. */ static int do_set_fan_div(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -342,7 +339,7 @@ static int do_set_fan_div(struct device *dev, unsigned long val) ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1, data->fan_cmd1); data->valid = false; out: @@ -354,7 +351,6 @@ static int do_set_fan_div(struct device *dev, unsigned long val) /* Set fan gear mode. Accepts either 0, 1 or 2. */ static int do_set_fan_gear_mode(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -379,7 +375,7 @@ static int do_set_fan_gear_mode(struct device *dev, unsigned long val) ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2, data->fan_cmd2); data->valid = false; out: @@ -391,7 +387,6 @@ static int do_set_fan_gear_mode(struct device *dev, unsigned long val) /* Set number of fan pulses per revolution. Accepts either 2 or 4. */ static int do_set_fan_pulses(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -410,7 +405,7 @@ static int do_set_fan_pulses(struct device *dev, unsigned long val) ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1, data->fan_cmd1); data->valid = false; out: @@ -422,7 +417,6 @@ static int do_set_fan_pulses(struct device *dev, unsigned long val) /* Set fan mode. Accepts either 1 (open-loop) or 2 (closed-loop). */ static int do_set_pwm_enable(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -444,15 +438,15 @@ static int do_set_pwm_enable(struct device *dev, unsigned long val) * value of 254 if it is 255 when switching to open-loop. */ if (data->set_cnt == 0xff) - i2c_smbus_write_byte_data(client, G762_REG_SET_CNT, - 254); + i2c_smbus_write_byte_data(data->client, + G762_REG_SET_CNT, 254); break; default: ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1, data->fan_cmd1); data->valid = false; out: @@ -464,7 +458,6 @@ static int do_set_pwm_enable(struct device *dev, unsigned long val) /* Set PWM polarity. Accepts either 0 (positive duty) or 1 (negative duty) */ static int do_set_pwm_polarity(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -483,7 +476,7 @@ static int do_set_pwm_polarity(struct device *dev, unsigned long val) ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1, data->fan_cmd1); data->valid = false; out: @@ -498,8 +491,8 @@ static int do_set_pwm_polarity(struct device *dev, unsigned long val) */ static int do_set_pwm(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); - struct g762_data *data = i2c_get_clientdata(client); + struct g762_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int ret; if (val > 255) @@ -519,7 +512,6 @@ static int do_set_pwm(struct device *dev, unsigned long val) */ static int do_set_fan_target(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -531,7 +523,7 @@ static int do_set_fan_target(struct device *dev, unsigned long val) G762_PULSE_FROM_REG(data->fan_cmd1), G762_CLKDIV_FROM_REG(data->fan_cmd1), G762_GEARMULT_FROM_REG(data->fan_cmd2)); - ret = i2c_smbus_write_byte_data(client, G762_REG_SET_CNT, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_SET_CNT, data->set_cnt); data->valid = false; mutex_unlock(&data->update_lock); @@ -542,7 +534,6 @@ static int do_set_fan_target(struct device *dev, unsigned long val) /* Set fan startup voltage. Accepted values are either 0, 1, 2 or 3. */ static int do_set_fan_startv(struct device *dev, unsigned long val) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); int ret; @@ -571,7 +562,7 @@ static int do_set_fan_startv(struct device *dev, unsigned long val) ret = -EINVAL; goto out; } - ret = i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD2, + ret = i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD2, data->fan_cmd2); data->valid = false; out: @@ -658,15 +649,12 @@ static int g762_of_prop_import_one(struct i2c_client *client, int (*psetter)(struct device *dev, unsigned long val)) { - const __be32 *prop; - int len, ret; + int ret; u32 pval; - prop = of_get_property(client->dev.of_node, pname, &len); - if (!prop || len != sizeof(u32)) + if (of_property_read_u32(client->dev.of_node, pname, &pval)) return 0; - pval = be32_to_cpu(prop[0]); dev_dbg(&client->dev, "found %s (%d)\n", pname, pval); ret = (*psetter)(&client->dev, pval); if (ret) @@ -1026,7 +1014,7 @@ static DEVICE_ATTR(fan1_pulses, S_IWUSR | S_IRUGO, get_fan_pulses, set_fan_pulses); /* Driver data */ -static struct attribute *g762_attributes[] = { +static struct attribute *g762_attrs[] = { &dev_attr_fan1_input.attr, &dev_attr_fan1_alarm.attr, &dev_attr_fan1_fault.attr, @@ -1039,9 +1027,7 @@ static struct attribute *g762_attributes[] = { NULL }; -static const struct attribute_group g762_group = { - .attrs = g762_attributes, -}; +ATTRIBUTE_GROUPS(g762); /* * Enable both fan failure detection and fan out of control protection. The @@ -1050,7 +1036,6 @@ static const struct attribute_group g762_group = { */ static inline int g762_fan_init(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); struct g762_data *data = g762_update_client(dev); if (IS_ERR(data)) @@ -1060,12 +1045,13 @@ static inline int g762_fan_init(struct device *dev) data->fan_cmd1 |= G762_REG_FAN_CMD1_DET_FAN_OOC; data->valid = false; - return i2c_smbus_write_byte_data(client, G762_REG_FAN_CMD1, + return i2c_smbus_write_byte_data(data->client, G762_REG_FAN_CMD1, data->fan_cmd1); } static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct g762_data *data; int ret; @@ -1073,7 +1059,7 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id) I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - data = devm_kzalloc(&client->dev, sizeof(struct g762_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct g762_data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -1082,7 +1068,7 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id) mutex_init(&data->update_lock); /* Enable fan failure detection and fan out of control protection */ - ret = g762_fan_init(&client->dev); + ret = g762_fan_init(dev); if (ret) return ret; @@ -1098,22 +1084,17 @@ static int g762_probe(struct i2c_client *client, const struct i2c_device_id *id) if (ret) goto clock_dis; - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, &g762_group); - if (ret) - goto clock_dis; - - data->hwmon_dev = hwmon_device_register(&client->dev); + data->hwmon_dev = devm_hwmon_device_register_with_groups(dev, + client->name, + data, + g762_groups); if (IS_ERR(data->hwmon_dev)) { ret = PTR_ERR(data->hwmon_dev); - goto sysfs_rem; + goto clock_dis; } return 0; - sysfs_rem: - sysfs_remove_group(&client->dev.kobj, &g762_group); - clock_dis: g762_of_clock_disable(client); @@ -1125,7 +1106,6 @@ static int g762_remove(struct i2c_client *client) struct g762_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &g762_group); g762_of_clock_disable(client); return 0; diff --git a/drivers/hwmon/gl518sm.c b/drivers/hwmon/gl518sm.c index 1e9830513045..0212c8317bca 100644 --- a/drivers/hwmon/gl518sm.c +++ b/drivers/hwmon/gl518sm.c @@ -114,7 +114,8 @@ static inline u8 FAN_TO_REG(long rpm, int div) /* Each client has this additional data */ struct gl518_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; enum chips type; struct mutex update_lock; @@ -137,33 +138,98 @@ struct gl518_data { u8 beep_enable; /* Boolean */ }; -static int gl518_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info); -static void gl518_init_client(struct i2c_client *client); -static int gl518_remove(struct i2c_client *client); -static int gl518_read_value(struct i2c_client *client, u8 reg); -static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value); -static struct gl518_data *gl518_update_device(struct device *dev); +/* + * Registers 0x07 to 0x0c are word-sized, others are byte-sized + * GL518 uses a high-byte first convention, which is exactly opposite to + * the SMBus standard. + */ +static int gl518_read_value(struct i2c_client *client, u8 reg) +{ + if ((reg >= 0x07) && (reg <= 0x0c)) + return i2c_smbus_read_word_swapped(client, reg); + else + return i2c_smbus_read_byte_data(client, reg); +} -static const struct i2c_device_id gl518_id[] = { - { "gl518sm", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl518_id); +static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) +{ + if ((reg >= 0x07) && (reg <= 0x0c)) + return i2c_smbus_write_word_swapped(client, reg, value); + else + return i2c_smbus_write_byte_data(client, reg, value); +} -/* This is the driver that will be inserted */ -static struct i2c_driver gl518_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "gl518sm", - }, - .probe = gl518_probe, - .remove = gl518_remove, - .id_table = gl518_id, - .detect = gl518_detect, - .address_list = normal_i2c, -}; +static struct gl518_data *gl518_update_device(struct device *dev) +{ + struct gl518_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int val; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + dev_dbg(&client->dev, "Starting gl518 update\n"); + + data->alarms = gl518_read_value(client, GL518_REG_INT); + data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); + + val = gl518_read_value(client, GL518_REG_VDD_LIMIT); + data->voltage_min[0] = val & 0xff; + data->voltage_max[0] = (val >> 8) & 0xff; + val = gl518_read_value(client, GL518_REG_VIN1_LIMIT); + data->voltage_min[1] = val & 0xff; + data->voltage_max[1] = (val >> 8) & 0xff; + val = gl518_read_value(client, GL518_REG_VIN2_LIMIT); + data->voltage_min[2] = val & 0xff; + data->voltage_max[2] = (val >> 8) & 0xff; + val = gl518_read_value(client, GL518_REG_VIN3_LIMIT); + data->voltage_min[3] = val & 0xff; + data->voltage_max[3] = (val >> 8) & 0xff; + + val = gl518_read_value(client, GL518_REG_FAN_COUNT); + data->fan_in[0] = (val >> 8) & 0xff; + data->fan_in[1] = val & 0xff; + + val = gl518_read_value(client, GL518_REG_FAN_LIMIT); + data->fan_min[0] = (val >> 8) & 0xff; + data->fan_min[1] = val & 0xff; + + data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN); + data->temp_max = + gl518_read_value(client, GL518_REG_TEMP_MAX); + data->temp_hyst = + gl518_read_value(client, GL518_REG_TEMP_HYST); + + val = gl518_read_value(client, GL518_REG_MISC); + data->fan_div[0] = (val >> 6) & 0x03; + data->fan_div[1] = (val >> 4) & 0x03; + data->fan_auto1 = (val >> 3) & 0x01; + + data->alarms &= data->alarm_mask; + + val = gl518_read_value(client, GL518_REG_CONF); + data->beep_enable = (val >> 2) & 1; + + if (data->type != gl518sm_r00) { + data->voltage_in[0] = + gl518_read_value(client, GL518_REG_VDD); + data->voltage_in[1] = + gl518_read_value(client, GL518_REG_VIN1); + data->voltage_in[2] = + gl518_read_value(client, GL518_REG_VIN2); + } + data->voltage_in[3] = + gl518_read_value(client, GL518_REG_VIN3); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} /* * Sysfs stuff @@ -228,8 +294,8 @@ 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); \ + struct gl518_data *data = dev_get_drvdata(dev); \ + struct i2c_client *client = data->client; \ long val; \ int err = kstrtol(buf, 10, &val); \ if (err) \ @@ -247,8 +313,8 @@ 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); \ + struct gl518_data *data = dev_get_drvdata(dev); \ + struct i2c_client *client = data->client; \ int regvalue; \ unsigned long val; \ int err = kstrtoul(buf, 10, &val); \ @@ -286,8 +352,8 @@ set(BEEP_MASK, beep_mask, beep_mask, GL518_REG_ALARM); static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); + struct gl518_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; int regvalue; unsigned long val; @@ -319,8 +385,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); + struct gl518_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int nr = to_sensor_dev_attr(attr)->index; int regvalue; unsigned long val; @@ -420,8 +486,8 @@ static ssize_t show_beep(struct device *dev, struct device_attribute *attr, static ssize_t set_beep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); + struct gl518_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int bitnr = to_sensor_dev_attr(attr)->index; unsigned long bit; int err; @@ -539,52 +605,6 @@ static int gl518_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } -static int gl518_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl518_data *data; - int err, revision; - - data = devm_kzalloc(&client->dev, sizeof(struct gl518_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - revision = gl518_read_value(client, GL518_REG_REVISION); - data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00; - mutex_init(&data->update_lock); - - /* Initialize the GL518SM chip */ - data->alarm_mask = 0xff; - gl518_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &gl518_group); - if (err) - return err; - if (data->type == gl518sm_r80) { - err = sysfs_create_group(&client->dev.kobj, &gl518_group_r80); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &gl518_group); - if (data->type == gl518sm_r80) - sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); - return err; -} - - /* * Called when we have found a new GL518SM. * Note that we preserve D4:NoFan2 and D2:beep_enable. @@ -605,110 +625,53 @@ static void gl518_init_client(struct i2c_client *client) gl518_write_value(client, GL518_REG_CONF, 0x40 | regvalue); } -static int gl518_remove(struct i2c_client *client) -{ - struct gl518_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &gl518_group); - if (data->type == gl518sm_r80) - sysfs_remove_group(&client->dev.kobj, &gl518_group_r80); - - return 0; -} - -/* - * Registers 0x07 to 0x0c are word-sized, others are byte-sized - * GL518 uses a high-byte first convention, which is exactly opposite to - * the SMBus standard. - */ -static int gl518_read_value(struct i2c_client *client, u8 reg) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_read_word_swapped(client, reg); - else - return i2c_smbus_read_byte_data(client, reg); -} - -static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_write_word_swapped(client, reg, value); - else - return i2c_smbus_write_byte_data(client, reg, value); -} - -static struct gl518_data *gl518_update_device(struct device *dev) +static int gl518_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client = to_i2c_client(dev); - struct gl518_data *data = i2c_get_clientdata(client); - int val; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - dev_dbg(&client->dev, "Starting gl518 update\n"); - - data->alarms = gl518_read_value(client, GL518_REG_INT); - data->beep_mask = gl518_read_value(client, GL518_REG_ALARM); - - val = gl518_read_value(client, GL518_REG_VDD_LIMIT); - data->voltage_min[0] = val & 0xff; - data->voltage_max[0] = (val >> 8) & 0xff; - val = gl518_read_value(client, GL518_REG_VIN1_LIMIT); - data->voltage_min[1] = val & 0xff; - data->voltage_max[1] = (val >> 8) & 0xff; - val = gl518_read_value(client, GL518_REG_VIN2_LIMIT); - data->voltage_min[2] = val & 0xff; - data->voltage_max[2] = (val >> 8) & 0xff; - val = gl518_read_value(client, GL518_REG_VIN3_LIMIT); - data->voltage_min[3] = val & 0xff; - data->voltage_max[3] = (val >> 8) & 0xff; - - val = gl518_read_value(client, GL518_REG_FAN_COUNT); - data->fan_in[0] = (val >> 8) & 0xff; - data->fan_in[1] = val & 0xff; - - val = gl518_read_value(client, GL518_REG_FAN_LIMIT); - data->fan_min[0] = (val >> 8) & 0xff; - data->fan_min[1] = val & 0xff; - - data->temp_in = gl518_read_value(client, GL518_REG_TEMP_IN); - data->temp_max = - gl518_read_value(client, GL518_REG_TEMP_MAX); - data->temp_hyst = - gl518_read_value(client, GL518_REG_TEMP_HYST); + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct gl518_data *data; + int revision; - val = gl518_read_value(client, GL518_REG_MISC); - data->fan_div[0] = (val >> 6) & 0x03; - data->fan_div[1] = (val >> 4) & 0x03; - data->fan_auto1 = (val >> 3) & 0x01; + data = devm_kzalloc(dev, sizeof(struct gl518_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - data->alarms &= data->alarm_mask; + data->client = client; + revision = gl518_read_value(client, GL518_REG_REVISION); + data->type = revision == 0x80 ? gl518sm_r80 : gl518sm_r00; + mutex_init(&data->update_lock); - val = gl518_read_value(client, GL518_REG_CONF); - data->beep_enable = (val >> 2) & 1; + /* Initialize the GL518SM chip */ + data->alarm_mask = 0xff; + gl518_init_client(client); - if (data->type != gl518sm_r00) { - data->voltage_in[0] = - gl518_read_value(client, GL518_REG_VDD); - data->voltage_in[1] = - gl518_read_value(client, GL518_REG_VIN1); - data->voltage_in[2] = - gl518_read_value(client, GL518_REG_VIN2); - } - data->voltage_in[3] = - gl518_read_value(client, GL518_REG_VIN3); + /* sysfs hooks */ + data->groups[0] = &gl518_group; + if (data->type == gl518sm_r80) + data->groups[1] = &gl518_group_r80; - data->last_updated = jiffies; - data->valid = 1; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - mutex_unlock(&data->update_lock); +static const struct i2c_device_id gl518_id[] = { + { "gl518sm", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, gl518_id); - return data; -} +static struct i2c_driver gl518_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "gl518sm", + }, + .probe = gl518_probe, + .id_table = gl518_id, + .detect = gl518_detect, + .address_list = normal_i2c, +}; module_i2c_driver(gl518_driver); diff --git a/drivers/hwmon/gl520sm.c b/drivers/hwmon/gl520sm.c index ed56e09c3dd7..dee93ec87d02 100644 --- a/drivers/hwmon/gl520sm.c +++ b/drivers/hwmon/gl520sm.c @@ -73,41 +73,10 @@ static const u8 GL520_REG_TEMP_MAX_HYST[] = { 0x06, 0x18 }; #define GL520_REG_BEEP_MASK 0x10 #define GL520_REG_BEEP_ENABLE GL520_REG_CONF -/* - * Function declarations - */ - -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info); -static void gl520_init_client(struct i2c_client *client); -static int gl520_remove(struct i2c_client *client); -static int gl520_read_value(struct i2c_client *client, u8 reg); -static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value); -static struct gl520_data *gl520_update_device(struct device *dev); - -/* Driver data */ -static const struct i2c_device_id gl520_id[] = { - { "gl520sm", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, gl520_id); - -static struct i2c_driver gl520_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "gl520sm", - }, - .probe = gl520_probe, - .remove = gl520_remove, - .id_table = gl520_id, - .detect = gl520_detect, - .address_list = normal_i2c, -}; - /* Client data */ struct gl520_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; char valid; /* zero until the following fields are valid */ unsigned long last_updated; /* in jiffies */ @@ -132,6 +101,102 @@ struct gl520_data { }; /* + * Registers 0x07 to 0x0c are word-sized, others are byte-sized + * GL520 uses a high-byte first convention + */ +static int gl520_read_value(struct i2c_client *client, u8 reg) +{ + if ((reg >= 0x07) && (reg <= 0x0c)) + return i2c_smbus_read_word_swapped(client, reg); + else + return i2c_smbus_read_byte_data(client, reg); +} + +static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value) +{ + if ((reg >= 0x07) && (reg <= 0x0c)) + return i2c_smbus_write_word_swapped(client, reg, value); + else + return i2c_smbus_write_byte_data(client, reg, value); +} + +static struct gl520_data *gl520_update_device(struct device *dev) +{ + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int val, i; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { + + dev_dbg(&client->dev, "Starting gl520sm update\n"); + + data->alarms = gl520_read_value(client, GL520_REG_ALARMS); + data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); + data->vid = gl520_read_value(client, + GL520_REG_VID_INPUT) & 0x1f; + + for (i = 0; i < 4; i++) { + data->in_input[i] = gl520_read_value(client, + GL520_REG_IN_INPUT[i]); + val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); + data->in_min[i] = val & 0xff; + data->in_max[i] = (val >> 8) & 0xff; + } + + val = gl520_read_value(client, GL520_REG_FAN_INPUT); + data->fan_input[0] = (val >> 8) & 0xff; + data->fan_input[1] = val & 0xff; + + val = gl520_read_value(client, GL520_REG_FAN_MIN); + data->fan_min[0] = (val >> 8) & 0xff; + data->fan_min[1] = val & 0xff; + + data->temp_input[0] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[0]); + data->temp_max[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX[0]); + data->temp_max_hyst[0] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[0]); + + val = gl520_read_value(client, GL520_REG_FAN_DIV); + data->fan_div[0] = (val >> 6) & 0x03; + data->fan_div[1] = (val >> 4) & 0x03; + data->fan_off = (val >> 2) & 0x01; + + data->alarms &= data->alarm_mask; + + val = gl520_read_value(client, GL520_REG_CONF); + data->beep_enable = !((val >> 2) & 1); + + /* Temp1 and Vin4 are the same input */ + if (data->two_temps) { + data->temp_input[1] = gl520_read_value(client, + GL520_REG_TEMP_INPUT[1]); + data->temp_max[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX[1]); + data->temp_max_hyst[1] = gl520_read_value(client, + GL520_REG_TEMP_MAX_HYST[1]); + } else { + data->in_input[4] = gl520_read_value(client, + GL520_REG_IN_INPUT[4]); + data->in_min[4] = gl520_read_value(client, + GL520_REG_IN_MIN[4]); + data->in_max[4] = gl520_read_value(client, + GL520_REG_IN_MAX[4]); + } + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} + +/* * Sysfs stuff */ @@ -191,8 +256,8 @@ static ssize_t get_in_max(struct device *dev, struct device_attribute *attr, static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; long v; @@ -225,8 +290,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; long v; @@ -326,8 +391,8 @@ static ssize_t get_fan_off(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; unsigned long v; @@ -365,8 +430,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; u8 r; unsigned long v; @@ -414,8 +479,8 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr, static ssize_t set_fan_off(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 r; unsigned long v; int err; @@ -482,8 +547,8 @@ static ssize_t get_temp_max_hyst(struct device *dev, static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; long v; int err; @@ -502,8 +567,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, static ssize_t set_temp_max_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int n = to_sensor_dev_attr(attr)->index; long v; int err; @@ -555,8 +620,8 @@ static ssize_t get_beep_mask(struct device *dev, struct device_attribute *attr, static ssize_t set_beep_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 r; unsigned long v; int err; @@ -579,8 +644,8 @@ static ssize_t set_beep_enable(struct device *dev, struct device_attribute static ssize_t set_beep_mask(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long r; int err; @@ -633,8 +698,8 @@ static ssize_t get_beep(struct device *dev, struct device_attribute *attr, static ssize_t set_beep(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); + struct gl520_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int bitnr = to_sensor_dev_attr(attr)->index; unsigned long bit; @@ -772,52 +837,6 @@ static int gl520_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } -static int gl520_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct gl520_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct gl520_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - mutex_init(&data->update_lock); - - /* Initialize the GL520SM chip */ - gl520_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &gl520_group); - if (err) - return err; - - if (data->two_temps) - err = sysfs_create_group(&client->dev.kobj, &gl520_group_temp2); - else - err = sysfs_create_group(&client->dev.kobj, &gl520_group_in4); - - if (err) - goto exit_remove_files; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &gl520_group); - sysfs_remove_group(&client->dev.kobj, &gl520_group_in4); - sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2); - return err; -} - - /* Called when we have found a new GL520SM. */ static void gl520_init_client(struct i2c_client *client) { @@ -856,115 +875,53 @@ static void gl520_init_client(struct i2c_client *client) gl520_write_value(client, GL520_REG_BEEP_MASK, data->beep_mask); } -static int gl520_remove(struct i2c_client *client) +static int gl520_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct gl520_data *data = i2c_get_clientdata(client); + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct gl520_data *data; - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &gl520_group); - sysfs_remove_group(&client->dev.kobj, &gl520_group_in4); - sysfs_remove_group(&client->dev.kobj, &gl520_group_temp2); + data = devm_kzalloc(dev, sizeof(struct gl520_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - return 0; -} + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + data->client = client; + /* Initialize the GL520SM chip */ + gl520_init_client(client); -/* - * Registers 0x07 to 0x0c are word-sized, others are byte-sized - * GL520 uses a high-byte first convention - */ -static int gl520_read_value(struct i2c_client *client, u8 reg) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_read_word_swapped(client, reg); - else - return i2c_smbus_read_byte_data(client, reg); -} + /* sysfs hooks */ + data->groups[0] = &gl520_group; -static int gl520_write_value(struct i2c_client *client, u8 reg, u16 value) -{ - if ((reg >= 0x07) && (reg <= 0x0c)) - return i2c_smbus_write_word_swapped(client, reg, value); + if (data->two_temps) + data->groups[1] = &gl520_group_temp2; else - return i2c_smbus_write_byte_data(client, reg, value); -} - - -static struct gl520_data *gl520_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct gl520_data *data = i2c_get_clientdata(client); - int val, i; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) { - - dev_dbg(&client->dev, "Starting gl520sm update\n"); - - data->alarms = gl520_read_value(client, GL520_REG_ALARMS); - data->beep_mask = gl520_read_value(client, GL520_REG_BEEP_MASK); - data->vid = gl520_read_value(client, - GL520_REG_VID_INPUT) & 0x1f; - - for (i = 0; i < 4; i++) { - data->in_input[i] = gl520_read_value(client, - GL520_REG_IN_INPUT[i]); - val = gl520_read_value(client, GL520_REG_IN_LIMIT[i]); - data->in_min[i] = val & 0xff; - data->in_max[i] = (val >> 8) & 0xff; - } - - val = gl520_read_value(client, GL520_REG_FAN_INPUT); - data->fan_input[0] = (val >> 8) & 0xff; - data->fan_input[1] = val & 0xff; + data->groups[1] = &gl520_group_in4; - val = gl520_read_value(client, GL520_REG_FAN_MIN); - data->fan_min[0] = (val >> 8) & 0xff; - data->fan_min[1] = val & 0xff; - - data->temp_input[0] = gl520_read_value(client, - GL520_REG_TEMP_INPUT[0]); - data->temp_max[0] = gl520_read_value(client, - GL520_REG_TEMP_MAX[0]); - data->temp_max_hyst[0] = gl520_read_value(client, - GL520_REG_TEMP_MAX_HYST[0]); - - val = gl520_read_value(client, GL520_REG_FAN_DIV); - data->fan_div[0] = (val >> 6) & 0x03; - data->fan_div[1] = (val >> 4) & 0x03; - data->fan_off = (val >> 2) & 0x01; - - data->alarms &= data->alarm_mask; - - val = gl520_read_value(client, GL520_REG_CONF); - data->beep_enable = !((val >> 2) & 1); - - /* Temp1 and Vin4 are the same input */ - if (data->two_temps) { - data->temp_input[1] = gl520_read_value(client, - GL520_REG_TEMP_INPUT[1]); - data->temp_max[1] = gl520_read_value(client, - GL520_REG_TEMP_MAX[1]); - data->temp_max_hyst[1] = gl520_read_value(client, - GL520_REG_TEMP_MAX_HYST[1]); - } else { - data->in_input[4] = gl520_read_value(client, - GL520_REG_IN_INPUT[4]); - data->in_min[4] = gl520_read_value(client, - GL520_REG_IN_MIN[4]); - data->in_max[4] = gl520_read_value(client, - GL520_REG_IN_MAX[4]); - } - - data->last_updated = jiffies; - data->valid = 1; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} - mutex_unlock(&data->update_lock); +static const struct i2c_device_id gl520_id[] = { + { "gl520sm", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, gl520_id); - return data; -} +static struct i2c_driver gl520_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "gl520sm", + }, + .probe = gl520_probe, + .id_table = gl520_id, + .detect = gl520_detect, + .address_list = normal_i2c, +}; module_i2c_driver(gl520_driver); diff --git a/drivers/hwmon/gpio-fan.c b/drivers/hwmon/gpio-fan.c index 2566c43dd1e9..4efa1734bdad 100644 --- a/drivers/hwmon/gpio-fan.c +++ b/drivers/hwmon/gpio-fan.c @@ -173,7 +173,7 @@ static int get_fan_speed_index(struct gpio_fan_data *fan_data) return -ENODEV; } -static int rpm_to_speed_index(struct gpio_fan_data *fan_data, int rpm) +static int rpm_to_speed_index(struct gpio_fan_data *fan_data, unsigned long rpm) { struct gpio_fan_speed *speed = fan_data->speed; int i; @@ -537,9 +537,10 @@ static int gpio_fan_probe(struct platform_device *pdev) } /* Make this driver part of hwmon class. */ - fan_data->hwmon_dev = hwmon_device_register_with_groups(&pdev->dev, - "gpio_fan", fan_data, - gpio_fan_groups); + fan_data->hwmon_dev = + devm_hwmon_device_register_with_groups(&pdev->dev, + "gpio_fan", fan_data, + gpio_fan_groups); if (IS_ERR(fan_data->hwmon_dev)) return PTR_ERR(fan_data->hwmon_dev); @@ -548,15 +549,6 @@ static int gpio_fan_probe(struct platform_device *pdev) return 0; } -static int gpio_fan_remove(struct platform_device *pdev) -{ - struct gpio_fan_data *fan_data = platform_get_drvdata(pdev); - - hwmon_device_unregister(fan_data->hwmon_dev); - - return 0; -} - #ifdef CONFIG_PM_SLEEP static int gpio_fan_suspend(struct device *dev) { @@ -588,7 +580,6 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume); static struct platform_driver gpio_fan_driver = { .probe = gpio_fan_probe, - .remove = gpio_fan_remove, .driver = { .name = "gpio-fan", .pm = GPIO_FAN_PM, diff --git a/drivers/hwmon/hih6130.c b/drivers/hwmon/hih6130.c index 7d68a08baaa8..0e01c4e13e33 100644 --- a/drivers/hwmon/hih6130.c +++ b/drivers/hwmon/hih6130.c @@ -46,7 +46,7 @@ * @write_length: length for I2C measurement request */ struct hih6130 { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex lock; bool valid; unsigned long last_update; @@ -62,7 +62,6 @@ struct hih6130 { */ static inline int hih6130_temp_ticks_to_millicelsius(int ticks) { - ticks = ticks >> 2; /* * from data sheet section 5.0 @@ -78,7 +77,6 @@ static inline int hih6130_temp_ticks_to_millicelsius(int ticks) */ static inline int hih6130_rh_ticks_to_per_cent_mille(int ticks) { - ticks &= ~0xC000; /* clear status bits */ /* * from data sheet section 4.0 @@ -89,15 +87,16 @@ static inline int hih6130_rh_ticks_to_per_cent_mille(int ticks) /** * hih6130_update_measurements() - get updated measurements from device - * @client: I2C client device + * @dev: device * * Returns 0 on success, else negative errno. */ -static int hih6130_update_measurements(struct i2c_client *client) +static int hih6130_update_measurements(struct device *dev) { + struct hih6130 *hih6130 = dev_get_drvdata(dev); + struct i2c_client *client = hih6130->client; int ret = 0; int t; - struct hih6130 *hih6130 = i2c_get_clientdata(client); unsigned char tmp[4]; struct i2c_msg msgs[1] = { { @@ -176,9 +175,10 @@ static ssize_t hih6130_show_temperature(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct hih6130 *hih6130 = i2c_get_clientdata(client); - int ret = hih6130_update_measurements(client); + struct hih6130 *hih6130 = dev_get_drvdata(dev); + int ret; + + ret = hih6130_update_measurements(dev); if (ret < 0) return ret; return sprintf(buf, "%d\n", hih6130->temperature); @@ -196,9 +196,10 @@ static ssize_t hih6130_show_temperature(struct device *dev, static ssize_t hih6130_show_humidity(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct hih6130 *hih6130 = i2c_get_clientdata(client); - int ret = hih6130_update_measurements(client); + struct hih6130 *hih6130 = dev_get_drvdata(dev); + int ret; + + ret = hih6130_update_measurements(dev); if (ret < 0) return ret; return sprintf(buf, "%d\n", hih6130->humidity); @@ -210,79 +211,37 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, hih6130_show_temperature, static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, hih6130_show_humidity, NULL, 0); -static struct attribute *hih6130_attributes[] = { +static struct attribute *hih6130_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_humidity1_input.dev_attr.attr, NULL }; -static const struct attribute_group hih6130_attr_group = { - .attrs = hih6130_attributes, -}; +ATTRIBUTE_GROUPS(hih6130); -/** - * hih6130_probe() - probe device - * @client: I2C client device - * @id: device ID - * - * Called by the I2C core when an entry in the ID table matches a - * device's name. - * Returns 0 on success. - */ static int hih6130_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct hih6130 *hih6130; - int err; + struct device *hwmon_dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { dev_err(&client->dev, "adapter does not support true I2C\n"); return -ENODEV; } - hih6130 = devm_kzalloc(&client->dev, sizeof(*hih6130), GFP_KERNEL); + hih6130 = devm_kzalloc(dev, sizeof(*hih6130), GFP_KERNEL); if (!hih6130) return -ENOMEM; - i2c_set_clientdata(client, hih6130); - + hih6130->client = client; mutex_init(&hih6130->lock); - err = sysfs_create_group(&client->dev.kobj, &hih6130_attr_group); - if (err) { - dev_dbg(&client->dev, "could not create sysfs files\n"); - return err; - } - - hih6130->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(hih6130->hwmon_dev)) { - dev_dbg(&client->dev, "unable to register hwmon device\n"); - err = PTR_ERR(hih6130->hwmon_dev); - goto fail_remove_sysfs; - } - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_QUICK)) - hih6130->write_length = 1; - - return 0; - -fail_remove_sysfs: - sysfs_remove_group(&client->dev.kobj, &hih6130_attr_group); - return err; -} - -/** - * hih6130_remove() - remove device - * @client: I2C client device - */ -static int hih6130_remove(struct i2c_client *client) -{ - struct hih6130 *hih6130 = i2c_get_clientdata(client); - - hwmon_device_unregister(hih6130->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &hih6130_attr_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + hih6130, + hih6130_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } /* Device ID table */ @@ -295,7 +254,6 @@ MODULE_DEVICE_TABLE(i2c, hih6130_id); static struct i2c_driver hih6130_driver = { .driver.name = "hih6130", .probe = hih6130_probe, - .remove = hih6130_remove, .id_table = hih6130_id, }; diff --git a/drivers/hwmon/htu21.c b/drivers/hwmon/htu21.c index 839086e0e951..4c3bbb72f82a 100644 --- a/drivers/hwmon/htu21.c +++ b/drivers/hwmon/htu21.c @@ -31,7 +31,7 @@ #define HTU21_RH_MEASUREMENT_HM 0xE5 struct htu21 { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex lock; bool valid; unsigned long last_update; @@ -59,10 +59,11 @@ static inline int htu21_rh_ticks_to_per_cent_mille(int ticks) return ((15625 * ticks) >> 13) - 6000; } -static int htu21_update_measurements(struct i2c_client *client) +static int htu21_update_measurements(struct device *dev) { + struct htu21 *htu21 = dev_get_drvdata(dev); + struct i2c_client *client = htu21->client; int ret = 0; - struct htu21 *htu21 = i2c_get_clientdata(client); mutex_lock(&htu21->lock); @@ -90,9 +91,10 @@ out: static ssize_t htu21_show_temperature(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct htu21 *htu21 = i2c_get_clientdata(client); - int ret = htu21_update_measurements(client); + struct htu21 *htu21 = dev_get_drvdata(dev); + int ret; + + ret = htu21_update_measurements(dev); if (ret < 0) return ret; return sprintf(buf, "%d\n", htu21->temperature); @@ -101,9 +103,10 @@ static ssize_t htu21_show_temperature(struct device *dev, static ssize_t htu21_show_humidity(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct htu21 *htu21 = i2c_get_clientdata(client); - int ret = htu21_update_measurements(client); + struct htu21 *htu21 = dev_get_drvdata(dev); + int ret; + + ret = htu21_update_measurements(dev); if (ret < 0) return ret; return sprintf(buf, "%d\n", htu21->humidity); @@ -114,21 +117,20 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, htu21_show_humidity, NULL, 0); -static struct attribute *htu21_attributes[] = { +static struct attribute *htu21_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_humidity1_input.dev_attr.attr, NULL }; -static const struct attribute_group htu21_group = { - .attrs = htu21_attributes, -}; +ATTRIBUTE_GROUPS(htu21); static int htu21_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct htu21 *htu21; - int err; + struct device *hwmon_dev; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)) { @@ -137,43 +139,17 @@ static int htu21_probe(struct i2c_client *client, return -ENODEV; } - htu21 = devm_kzalloc(&client->dev, sizeof(*htu21), GFP_KERNEL); + htu21 = devm_kzalloc(dev, sizeof(*htu21), GFP_KERNEL); if (!htu21) return -ENOMEM; - i2c_set_clientdata(client, htu21); - + htu21->client = client; mutex_init(&htu21->lock); - err = sysfs_create_group(&client->dev.kobj, &htu21_group); - if (err) { - dev_dbg(&client->dev, "could not create sysfs files\n"); - return err; - } - htu21->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(htu21->hwmon_dev)) { - dev_dbg(&client->dev, "unable to register hwmon device\n"); - err = PTR_ERR(htu21->hwmon_dev); - goto error; - } - - dev_info(&client->dev, "initialized\n"); - - return 0; - -error: - sysfs_remove_group(&client->dev.kobj, &htu21_group); - return err; -} - -static int htu21_remove(struct i2c_client *client) -{ - struct htu21 *htu21 = i2c_get_clientdata(client); - - hwmon_device_unregister(htu21->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &htu21_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + htu21, + htu21_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id htu21_id[] = { @@ -188,7 +164,6 @@ static struct i2c_driver htu21_driver = { .name = "htu21", }, .probe = htu21_probe, - .remove = htu21_remove, .id_table = htu21_id, }; diff --git a/drivers/hwmon/ibmpowernv.c b/drivers/hwmon/ibmpowernv.c new file mode 100644 index 000000000000..d2bf2c97ae70 --- /dev/null +++ b/drivers/hwmon/ibmpowernv.c @@ -0,0 +1,363 @@ +/* + * IBM PowerNV platform sensors for temperature/fan/voltage/power + * Copyright (C) 2014 IBM + * + * 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. + */ + +#define DRVNAME "ibmpowernv" +#define pr_fmt(fmt) DRVNAME ": " fmt + +#include <linux/init.h> +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/of.h> +#include <linux/slab.h> + +#include <linux/platform_device.h> +#include <asm/opal.h> +#include <linux/err.h> + +#define MAX_ATTR_LEN 32 + +/* Sensor suffix name from DT */ +#define DT_FAULT_ATTR_SUFFIX "faulted" +#define DT_DATA_ATTR_SUFFIX "data" +#define DT_THRESHOLD_ATTR_SUFFIX "thrs" + +/* + * Enumerates all the types of sensors in the POWERNV platform and does index + * into 'struct sensor_group' + */ +enum sensors { + FAN, + AMBIENT_TEMP, + POWER_SUPPLY, + POWER_INPUT, + MAX_SENSOR_TYPE, +}; + +static struct sensor_group { + const char *name; + const char *compatible; + struct attribute_group group; + u32 attr_count; +} sensor_groups[] = { + {"fan", "ibm,opal-sensor-cooling-fan"}, + {"temp", "ibm,opal-sensor-amb-temp"}, + {"in", "ibm,opal-sensor-power-supply"}, + {"power", "ibm,opal-sensor-power"} +}; + +struct sensor_data { + u32 id; /* An opaque id of the firmware for each sensor */ + enum sensors type; + char name[MAX_ATTR_LEN]; + struct device_attribute dev_attr; +}; + +struct platform_data { + const struct attribute_group *attr_groups[MAX_SENSOR_TYPE + 1]; + u32 sensors_count; /* Total count of sensors from each group */ +}; + +/* Platform device representing all the ibmpowernv sensors */ +static struct platform_device *pdevice; + +static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, + char *buf) +{ + struct sensor_data *sdata = container_of(devattr, struct sensor_data, + dev_attr); + ssize_t ret; + u32 x; + + ret = opal_get_sensor_data(sdata->id, &x); + if (ret) + return ret; + + /* Convert temperature to milli-degrees */ + if (sdata->type == AMBIENT_TEMP) + x *= 1000; + /* Convert power to micro-watts */ + else if (sdata->type == POWER_INPUT) + x *= 1000000; + + return sprintf(buf, "%u\n", x); +} + +static int __init get_sensor_index_attr(const char *name, u32 *index, + char *attr) +{ + char *hash_pos = strchr(name, '#'); + char buf[8] = { 0 }; + char *dash_pos; + u32 copy_len; + int err; + + if (!hash_pos) + return -EINVAL; + + dash_pos = strchr(hash_pos, '-'); + if (!dash_pos) + return -EINVAL; + + copy_len = dash_pos - hash_pos - 1; + if (copy_len >= sizeof(buf)) + return -EINVAL; + + strncpy(buf, hash_pos + 1, copy_len); + + err = kstrtou32(buf, 10, index); + if (err) + return err; + + strncpy(attr, dash_pos + 1, MAX_ATTR_LEN); + + return 0; +} + +/* + * This function translates the DT node name into the 'hwmon' attribute name. + * IBMPOWERNV device node appear like cooling-fan#2-data, amb-temp#1-thrs etc. + * which need to be mapped as fan2_input, temp1_max respectively before + * populating them inside hwmon device class. + */ +static int __init create_hwmon_attr_name(struct device *dev, enum sensors type, + const char *node_name, + char *hwmon_attr_name) +{ + char attr_suffix[MAX_ATTR_LEN]; + char *attr_name; + u32 index; + int err; + + err = get_sensor_index_attr(node_name, &index, attr_suffix); + if (err) { + dev_err(dev, "Sensor device node name '%s' is invalid\n", + node_name); + return err; + } + + if (!strcmp(attr_suffix, DT_FAULT_ATTR_SUFFIX)) { + attr_name = "fault"; + } else if (!strcmp(attr_suffix, DT_DATA_ATTR_SUFFIX)) { + attr_name = "input"; + } else if (!strcmp(attr_suffix, DT_THRESHOLD_ATTR_SUFFIX)) { + if (type == AMBIENT_TEMP) + attr_name = "max"; + else if (type == FAN) + attr_name = "min"; + else + return -ENOENT; + } else { + return -ENOENT; + } + + snprintf(hwmon_attr_name, MAX_ATTR_LEN, "%s%d_%s", + sensor_groups[type].name, index, attr_name); + return 0; +} + +static int __init populate_attr_groups(struct platform_device *pdev) +{ + struct platform_data *pdata = platform_get_drvdata(pdev); + const struct attribute_group **pgroups = pdata->attr_groups; + struct device_node *opal, *np; + enum sensors type; + + opal = of_find_node_by_path("/ibm,opal/sensors"); + if (!opal) { + dev_err(&pdev->dev, "Opal node 'sensors' not found\n"); + return -ENODEV; + } + + for_each_child_of_node(opal, np) { + if (np->name == NULL) + continue; + + for (type = 0; type < MAX_SENSOR_TYPE; type++) + if (of_device_is_compatible(np, + sensor_groups[type].compatible)) { + sensor_groups[type].attr_count++; + break; + } + } + + of_node_put(opal); + + for (type = 0; type < MAX_SENSOR_TYPE; type++) { + sensor_groups[type].group.attrs = devm_kzalloc(&pdev->dev, + sizeof(struct attribute *) * + (sensor_groups[type].attr_count + 1), + GFP_KERNEL); + if (!sensor_groups[type].group.attrs) + return -ENOMEM; + + pgroups[type] = &sensor_groups[type].group; + pdata->sensors_count += sensor_groups[type].attr_count; + sensor_groups[type].attr_count = 0; + } + + return 0; +} + +/* + * Iterate through the device tree for each child of 'sensors' node, create + * a sysfs attribute file, the file is named by translating the DT node name + * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max + * etc.. + */ +static int __init create_device_attrs(struct platform_device *pdev) +{ + struct platform_data *pdata = platform_get_drvdata(pdev); + const struct attribute_group **pgroups = pdata->attr_groups; + struct device_node *opal, *np; + struct sensor_data *sdata; + u32 sensor_id; + enum sensors type; + u32 count = 0; + int err = 0; + + opal = of_find_node_by_path("/ibm,opal/sensors"); + sdata = devm_kzalloc(&pdev->dev, pdata->sensors_count * sizeof(*sdata), + GFP_KERNEL); + if (!sdata) { + err = -ENOMEM; + goto exit_put_node; + } + + for_each_child_of_node(opal, np) { + if (np->name == NULL) + continue; + + for (type = 0; type < MAX_SENSOR_TYPE; type++) + if (of_device_is_compatible(np, + sensor_groups[type].compatible)) + break; + + if (type == MAX_SENSOR_TYPE) + continue; + + if (of_property_read_u32(np, "sensor-id", &sensor_id)) { + dev_info(&pdev->dev, + "'sensor-id' missing in the node '%s'\n", + np->name); + continue; + } + + sdata[count].id = sensor_id; + sdata[count].type = type; + err = create_hwmon_attr_name(&pdev->dev, type, np->name, + sdata[count].name); + if (err) + goto exit_put_node; + + sysfs_attr_init(&sdata[count].dev_attr.attr); + sdata[count].dev_attr.attr.name = sdata[count].name; + sdata[count].dev_attr.attr.mode = S_IRUGO; + sdata[count].dev_attr.show = show_sensor; + + pgroups[type]->attrs[sensor_groups[type].attr_count++] = + &sdata[count++].dev_attr.attr; + } + +exit_put_node: + of_node_put(opal); + return err; +} + +static int __init ibmpowernv_probe(struct platform_device *pdev) +{ + struct platform_data *pdata; + struct device *hwmon_dev; + int err; + + pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); + if (!pdata) + return -ENOMEM; + + platform_set_drvdata(pdev, pdata); + pdata->sensors_count = 0; + err = populate_attr_groups(pdev); + if (err) + return err; + + /* Create sysfs attribute data for each sensor found in the DT */ + err = create_device_attrs(pdev); + if (err) + return err; + + /* Finally, register with hwmon */ + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, DRVNAME, + pdata, + pdata->attr_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static struct platform_driver ibmpowernv_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, +}; + +static int __init ibmpowernv_init(void) +{ + int err; + + pdevice = platform_device_alloc(DRVNAME, 0); + if (!pdevice) { + pr_err("Device allocation failed\n"); + err = -ENOMEM; + goto exit; + } + + err = platform_device_add(pdevice); + if (err) { + pr_err("Device addition failed (%d)\n", err); + goto exit_device_put; + } + + err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe); + if (err) { + pr_err("Platfrom driver probe failed\n"); + goto exit_device_del; + } + + return 0; + +exit_device_del: + platform_device_del(pdevice); +exit_device_put: + platform_device_put(pdevice); +exit: + return err; +} + +static void __exit ibmpowernv_exit(void) +{ + platform_driver_unregister(&ibmpowernv_driver); + platform_device_unregister(pdevice); +} + +MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>"); +MODULE_DESCRIPTION("IBM POWERNV platform sensors"); +MODULE_LICENSE("GPL"); + +module_init(ibmpowernv_init); +module_exit(ibmpowernv_exit); diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index ebbb9f4f27a3..84d791bdb62d 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c @@ -125,7 +125,8 @@ #define FAN_SPEED_LEN 5 struct pem_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[4]; struct mutex update_lock; bool valid; @@ -160,8 +161,8 @@ abort: static struct pem_data *pem_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct pem_data *data = i2c_get_clientdata(client); + struct pem_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; struct pem_data *ret = data; mutex_lock(&data->update_lock); @@ -444,18 +445,20 @@ static int pem_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = client->adapter; + struct device *dev = &client->dev; + struct device *hwmon_dev; struct pem_data *data; - int ret; + int ret, idx = 0; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_BYTE)) return -ENODEV; - data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); /* @@ -471,14 +474,12 @@ static int pem_probe(struct i2c_client *client, if (ret < 0) return ret; - dev_info(&client->dev, "Firmware revision %d.%d.%d\n", + dev_info(dev, "Firmware revision %d.%d.%d\n", data->firmware_rev[0], data->firmware_rev[1], data->firmware_rev[2]); - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, &pem_group); - if (ret) - return ret; + /* sysfs hooks */ + data->groups[idx++] = &pem_group; /* * Check if input readings are supported. @@ -501,12 +502,9 @@ static int pem_probe(struct i2c_client *client, data->input_string[2] || data->input_string[3])) data->input_length = sizeof(data->input_string); } - ret = 0; - if (data->input_length) { - ret = sysfs_create_group(&client->dev.kobj, &pem_input_group); - if (ret) - goto out_remove_groups; - } + + if (data->input_length) + data->groups[idx++] = &pem_input_group; /* * Check if fan speed readings are supported. @@ -520,37 +518,12 @@ static int pem_probe(struct i2c_client *client, if (!ret && (data->fan_speed[0] || data->fan_speed[1] || data->fan_speed[2] || data->fan_speed[3])) { data->fans_supported = true; - ret = sysfs_create_group(&client->dev.kobj, &pem_fan_group); - if (ret) - goto out_remove_groups; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_remove_groups; + data->groups[idx++] = &pem_fan_group; } - return 0; - -out_remove_groups: - sysfs_remove_group(&client->dev.kobj, &pem_input_group); - sysfs_remove_group(&client->dev.kobj, &pem_fan_group); - sysfs_remove_group(&client->dev.kobj, &pem_group); - return ret; -} - -static int pem_remove(struct i2c_client *client) -{ - struct pem_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - - sysfs_remove_group(&client->dev.kobj, &pem_input_group); - sysfs_remove_group(&client->dev.kobj, &pem_fan_group); - sysfs_remove_group(&client->dev.kobj, &pem_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id pem_id[] = { @@ -564,7 +537,6 @@ static struct i2c_driver pem_driver = { .name = "lineage_pem", }, .probe = pem_probe, - .remove = pem_remove, .id_table = pem_id, }; diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 848b9611151f..33bfdb444138 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c @@ -126,24 +126,17 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4c, 0x4e, I2C_CLIENT_END }; #define FAN_TO_REG(val) ((val) <= 82 ? 0xFFFC : \ (5400000 / (val)) & 0xFFFC) #define TEMP8_FROM_REG(reg) ((reg) * 1000) -#define TEMP8_TO_REG(val) ((val) <= -128000 ? -128 : \ - (val) >= 127000 ? 127 : \ - (val) < 0 ? ((val) - 500) / 1000 : \ - ((val) + 500) / 1000) -#define TEMP8U_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 255000 ? 255 : \ - ((val) + 500) / 1000) +#define TEMP8_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), -128000, \ + 127000), 1000) +#define TEMP8U_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, \ + 255000), 1000) #define TEMP11_FROM_REG(reg) ((reg) / 32 * 125) -#define TEMP11_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ - (val) >= 127875 ? 0x7FE0 : \ - (val) < 0 ? ((val) - 62) / 125 * 32 : \ - ((val) + 62) / 125 * 32) -#define TEMP11U_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 255875 ? 0xFFE0 : \ - ((val) + 62) / 125 * 32) -#define HYST_TO_REG(val) ((val) <= 0 ? 0 : \ - (val) >= 127000 ? 127 : \ - ((val) + 500) / 1000) +#define TEMP11_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), -128000, \ + 127875), 125) * 32) +#define TEMP11U_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), 0, \ + 255875), 125) * 32) +#define HYST_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \ + 1000) #define UPDATE_INTERVAL(max, rate) \ ((1000 << (LM63_MAX_CONVRATE - (rate))) / (max)) diff --git a/drivers/hwmon/lm75.c b/drivers/hwmon/lm75.c index 479ffbeed3f8..d16dbb33a531 100644 --- a/drivers/hwmon/lm75.c +++ b/drivers/hwmon/lm75.c @@ -52,6 +52,7 @@ enum lm75_type { /* keep sorted in alphabetical order */ tmp100, tmp101, tmp105, + tmp112, tmp175, tmp275, tmp75, @@ -255,6 +256,12 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) data->sample_time = HZ; clr_mask |= 1 << 7; /* not one-shot mode */ break; + case tmp112: + set_mask |= 3 << 5; /* 12-bit mode */ + clr_mask |= 1 << 7; /* not one-shot mode */ + data->resolution = 12; + data->sample_time = HZ / 4; + break; case tmp105: case tmp175: case tmp275: @@ -323,6 +330,7 @@ static const struct i2c_device_id lm75_ids[] = { { "tmp100", tmp100, }, { "tmp101", tmp101, }, { "tmp105", tmp105, }, + { "tmp112", tmp112, }, { "tmp175", tmp175, }, { "tmp275", tmp275, }, { "tmp75", tmp75, }, diff --git a/drivers/hwmon/lm77.c b/drivers/hwmon/lm77.c index 5ceb443b938d..69b05cc2f60e 100644 --- a/drivers/hwmon/lm77.c +++ b/drivers/hwmon/lm77.c @@ -80,8 +80,7 @@ struct lm77_data { */ static inline s16 LM77_TEMP_TO_REG(int temp) { - int ntemp = clamp_val(temp, LM77_TEMP_MIN, LM77_TEMP_MAX); - return (ntemp / 500) * 8; + return (temp / 500) * 8; } static inline int LM77_TEMP_FROM_REG(s16 reg) @@ -175,6 +174,7 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, if (err) return err; + val = clamp_val(val, LM77_TEMP_MIN, LM77_TEMP_MAX); mutex_lock(&data->update_lock); data->temp[nr] = val; lm77_write_value(client, temp_regs[nr], LM77_TEMP_TO_REG(val)); @@ -192,15 +192,16 @@ static ssize_t set_temp_hyst(struct device *dev, { struct lm77_data *data = dev_get_drvdata(dev); struct i2c_client *client = data->client; - unsigned long val; + long val; int err; - err = kstrtoul(buf, 10, &val); + err = kstrtol(buf, 10, &val); if (err) return err; mutex_lock(&data->update_lock); - data->temp[t_hyst] = data->temp[t_crit] - val; + val = clamp_val(data->temp[t_crit] - val, LM77_TEMP_MIN, LM77_TEMP_MAX); + data->temp[t_hyst] = val; lm77_write_value(client, LM77_REG_TEMP_HYST, LM77_TEMP_TO_REG(data->temp[t_hyst])); mutex_unlock(&data->update_lock); diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index 9efadfc851bc..759661c7d480 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c @@ -108,7 +108,7 @@ static inline int FAN_FROM_REG(u8 val, int div) * TEMP: mC (-128C to +127C) * REG: 1C/bit, two's complement */ -static inline s8 TEMP_TO_REG(int val) +static inline s8 TEMP_TO_REG(long val) { int nval = clamp_val(val, -128000, 127000) ; return nval < 0 ? (nval - 500) / 1000 : (nval + 500) / 1000; @@ -123,7 +123,6 @@ static inline int TEMP_FROM_REG(s8 val) struct lm78_data { struct i2c_client *client; - struct device *hwmon_dev; struct mutex lock; enum chips type; @@ -468,7 +467,7 @@ static SENSOR_DEVICE_ATTR(fan2_alarm, S_IRUGO, show_alarm, NULL, 7); static SENSOR_DEVICE_ATTR(fan3_alarm, S_IRUGO, show_alarm, NULL, 11); static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4); -static struct attribute *lm78_attributes[] = { +static struct attribute *lm78_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_min.dev_attr.attr, &sensor_dev_attr_in0_max.dev_attr.attr, @@ -519,9 +518,7 @@ static struct attribute *lm78_attributes[] = { NULL }; -static const struct attribute_group lm78_group = { - .attrs = lm78_attributes, -}; +ATTRIBUTE_GROUPS(lm78); /* * ISA related code @@ -533,19 +530,6 @@ static struct platform_device *pdev; static unsigned short isa_address = 0x290; -/* - * I2C devices get this name attribute automatically, but for ISA devices - * we must create it by ourselves. - */ -static ssize_t show_name(struct device *dev, struct device_attribute - *devattr, char *buf) -{ - struct lm78_data *data = dev_get_drvdata(dev); - - return sprintf(buf, "%s\n", data->name); -} -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - static struct lm78_data *lm78_data_if_isa(void) { return pdev ? platform_get_drvdata(pdev) : NULL; @@ -661,46 +645,23 @@ static int lm78_i2c_detect(struct i2c_client *client, static int lm78_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct lm78_data *data; - int err; - data = devm_kzalloc(&client->dev, sizeof(struct lm78_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); data->client = client; data->type = id->driver_data; /* Initialize the LM78 chip */ lm78_init_device(data); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm78_group); - if (err) - return err; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto error; - } - - return 0; - -error: - sysfs_remove_group(&client->dev.kobj, &lm78_group); - return err; -} - -static int lm78_i2c_remove(struct i2c_client *client) -{ - struct lm78_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm78_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, lm78_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id lm78_i2c_id[] = { @@ -716,7 +677,6 @@ static struct i2c_driver lm78_driver = { .name = "lm78", }, .probe = lm78_i2c_probe, - .remove = lm78_i2c_remove, .id_table = lm78_i2c_id, .detect = lm78_i2c_detect, .address_list = normal_i2c, @@ -839,17 +799,18 @@ static struct lm78_data *lm78_update_device(struct device *dev) #ifdef CONFIG_ISA static int lm78_isa_probe(struct platform_device *pdev) { - int err; + struct device *dev = &pdev->dev; + struct device *hwmon_dev; struct lm78_data *data; struct resource *res; /* Reserve the ISA region */ res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!devm_request_region(&pdev->dev, res->start + LM78_ADDR_REG_OFFSET, + if (!devm_request_region(dev, res->start + LM78_ADDR_REG_OFFSET, 2, "lm78")) return -EBUSY; - data = devm_kzalloc(&pdev->dev, sizeof(struct lm78_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct lm78_data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -868,37 +829,9 @@ static int lm78_isa_probe(struct platform_device *pdev) /* Initialize the LM78 chip */ lm78_init_device(data); - /* Register sysfs hooks */ - err = sysfs_create_group(&pdev->dev.kobj, &lm78_group); - if (err) - goto exit_remove_files; - err = device_create_file(&pdev->dev, &dev_attr_name); - if (err) - goto exit_remove_files; - - data->hwmon_dev = hwmon_device_register(&pdev->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - - exit_remove_files: - sysfs_remove_group(&pdev->dev.kobj, &lm78_group); - device_remove_file(&pdev->dev, &dev_attr_name); - return err; -} - -static int lm78_isa_remove(struct platform_device *pdev) -{ - struct lm78_data *data = platform_get_drvdata(pdev); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&pdev->dev.kobj, &lm78_group); - device_remove_file(&pdev->dev, &dev_attr_name); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name, + data, lm78_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static struct platform_driver lm78_isa_driver = { @@ -907,7 +840,6 @@ static struct platform_driver lm78_isa_driver = { .name = "lm78", }, .probe = lm78_isa_probe, - .remove = lm78_isa_remove, }; /* return 1 if a supported chip is found, 0 otherwise */ diff --git a/drivers/hwmon/lm85.c b/drivers/hwmon/lm85.c index b0129a54e1a6..2b4b419273fe 100644 --- a/drivers/hwmon/lm85.c +++ b/drivers/hwmon/lm85.c @@ -121,7 +121,6 @@ enum chips { #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 @@ -155,7 +154,7 @@ static inline u16 FAN_TO_REG(unsigned long val) /* Temperature is reported in .001 degC increments */ #define TEMP_TO_REG(val) \ - clamp_val(SCALE(val, 1000, 1), -127, 127) + DIV_ROUND_CLOSEST(clamp_val((val), -127000, 127000), 1000) #define TEMPEXT_FROM_REG(val, ext) \ SCALE(((val) << 4) + (ext), 16, 1000) #define TEMP_FROM_REG(val) ((val) * 1000) @@ -189,7 +188,7 @@ static const int lm85_range_map[] = { 13300, 16000, 20000, 26600, 32000, 40000, 53300, 80000 }; -static int RANGE_TO_REG(int range) +static int RANGE_TO_REG(long range) { int i; @@ -211,7 +210,7 @@ static const int adm1027_freq_map[8] = { /* 1 Hz */ 11, 15, 22, 29, 35, 44, 59, 88 }; -static int FREQ_TO_REG(const int *map, int freq) +static int FREQ_TO_REG(const int *map, unsigned long freq) { int i; @@ -303,7 +302,8 @@ struct lm85_autofan { * The structure is dynamically allocated. */ struct lm85_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[6]; const int *freq_map; enum chips type; @@ -334,44 +334,235 @@ struct lm85_data { struct lm85_zone zone[3]; }; -static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info); -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int lm85_remove(struct i2c_client *client); +static int lm85_read_value(struct i2c_client *client, u8 reg) +{ + int res; -static int lm85_read_value(struct i2c_client *client, u8 reg); -static void lm85_write_value(struct i2c_client *client, u8 reg, int value); -static struct lm85_data *lm85_update_device(struct device *dev); + /* What size location is it? */ + switch (reg) { + case LM85_REG_FAN(0): /* Read WORD data */ + case LM85_REG_FAN(1): + case LM85_REG_FAN(2): + case LM85_REG_FAN(3): + case LM85_REG_FAN_MIN(0): + case LM85_REG_FAN_MIN(1): + case LM85_REG_FAN_MIN(2): + case LM85_REG_FAN_MIN(3): + case LM85_REG_ALARM1: /* Read both bytes at once */ + res = i2c_smbus_read_byte_data(client, reg) & 0xff; + res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; + break; + default: /* Read BYTE data */ + res = i2c_smbus_read_byte_data(client, reg); + break; + } + return res; +} -static const struct i2c_device_id lm85_id[] = { - { "adm1027", adm1027 }, - { "adt7463", adt7463 }, - { "adt7468", adt7468 }, - { "lm85", lm85 }, - { "lm85b", lm85 }, - { "lm85c", lm85 }, - { "emc6d100", emc6d100 }, - { "emc6d101", emc6d100 }, - { "emc6d102", emc6d102 }, - { "emc6d103", emc6d103 }, - { "emc6d103s", emc6d103s }, - { } -}; -MODULE_DEVICE_TABLE(i2c, lm85_id); +static void lm85_write_value(struct i2c_client *client, u8 reg, int value) +{ + switch (reg) { + case LM85_REG_FAN(0): /* Write WORD data */ + case LM85_REG_FAN(1): + case LM85_REG_FAN(2): + case LM85_REG_FAN(3): + case LM85_REG_FAN_MIN(0): + case LM85_REG_FAN_MIN(1): + case LM85_REG_FAN_MIN(2): + case LM85_REG_FAN_MIN(3): + /* NOTE: ALARM is read only, so not included here */ + i2c_smbus_write_byte_data(client, reg, value & 0xff); + i2c_smbus_write_byte_data(client, reg + 1, value >> 8); + break; + default: /* Write BYTE data */ + i2c_smbus_write_byte_data(client, reg, value); + break; + } +} -static struct i2c_driver lm85_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "lm85", - }, - .probe = lm85_probe, - .remove = lm85_remove, - .id_table = lm85_id, - .detect = lm85_detect, - .address_list = normal_i2c, -}; +static struct lm85_data *lm85_update_device(struct device *dev) +{ + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i; + + mutex_lock(&data->update_lock); + + if (!data->valid || + time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { + /* Things that change quickly */ + dev_dbg(&client->dev, "Reading sensor values\n"); + + /* + * Have to read extended bits first to "freeze" the + * more significant bits that are read later. + * There are 2 additional resolution bits per channel and we + * have room for 4, so we shift them to the left. + */ + if (data->type == adm1027 || data->type == adt7463 || + data->type == adt7468) { + int ext1 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + ADM1027_REG_EXTEND_ADC2); + int val = (ext1 << 8) + ext2; + + for (i = 0; i <= 4; i++) + data->in_ext[i] = + ((val >> (i * 2)) & 0x03) << 2; + + for (i = 0; i <= 2; i++) + data->temp_ext[i] = + (val >> ((i + 4) * 2)) & 0x0c; + } + + data->vid = lm85_read_value(client, LM85_REG_VID); + + for (i = 0; i <= 3; ++i) { + data->in[i] = + lm85_read_value(client, LM85_REG_IN(i)); + data->fan[i] = + lm85_read_value(client, LM85_REG_FAN(i)); + } + + if (!data->has_vid5) + data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); + + if (data->type == adt7468) + data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); + for (i = 0; i <= 2; ++i) { + data->temp[i] = + lm85_read_value(client, LM85_REG_TEMP(i)); + data->pwm[i] = + lm85_read_value(client, LM85_REG_PWM(i)); + + if (IS_ADT7468_OFF64(data)) + data->temp[i] -= 64; + } + + data->alarms = lm85_read_value(client, LM85_REG_ALARM1); + + if (data->type == emc6d100) { + /* Three more voltage sensors */ + for (i = 5; i <= 7; ++i) { + data->in[i] = lm85_read_value(client, + EMC6D100_REG_IN(i)); + } + /* More alarm bits */ + data->alarms |= lm85_read_value(client, + EMC6D100_REG_ALARM3) << 16; + } else if (data->type == emc6d102 || data->type == emc6d103 || + data->type == emc6d103s) { + /* + * Have to read LSB bits after the MSB ones because + * the reading of the MSB bits has frozen the + * LSBs (backward from the ADM1027). + */ + int ext1 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC1); + int ext2 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC2); + int ext3 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC3); + int ext4 = lm85_read_value(client, + EMC6D102_REG_EXTEND_ADC4); + data->in_ext[0] = ext3 & 0x0f; + data->in_ext[1] = ext4 & 0x0f; + data->in_ext[2] = ext4 >> 4; + data->in_ext[3] = ext3 >> 4; + data->in_ext[4] = ext2 >> 4; + + data->temp_ext[0] = ext1 & 0x0f; + data->temp_ext[1] = ext2 & 0x0f; + data->temp_ext[2] = ext1 >> 4; + } + + data->last_reading = jiffies; + } /* last_reading */ + + if (!data->valid || + time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { + /* Things that don't change often */ + dev_dbg(&client->dev, "Reading config values\n"); + + for (i = 0; i <= 3; ++i) { + data->in_min[i] = + lm85_read_value(client, LM85_REG_IN_MIN(i)); + data->in_max[i] = + lm85_read_value(client, LM85_REG_IN_MAX(i)); + data->fan_min[i] = + lm85_read_value(client, LM85_REG_FAN_MIN(i)); + } + + if (!data->has_vid5) { + data->in_min[4] = lm85_read_value(client, + LM85_REG_IN_MIN(4)); + data->in_max[4] = lm85_read_value(client, + LM85_REG_IN_MAX(4)); + } + + if (data->type == emc6d100) { + for (i = 5; i <= 7; ++i) { + data->in_min[i] = lm85_read_value(client, + EMC6D100_REG_IN_MIN(i)); + data->in_max[i] = lm85_read_value(client, + EMC6D100_REG_IN_MAX(i)); + } + } + + for (i = 0; i <= 2; ++i) { + int val; + + data->temp_min[i] = + lm85_read_value(client, LM85_REG_TEMP_MIN(i)); + data->temp_max[i] = + lm85_read_value(client, LM85_REG_TEMP_MAX(i)); + + data->autofan[i].config = + lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); + val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); + data->pwm_freq[i] = val & 0x07; + data->zone[i].range = val >> 4; + data->autofan[i].min_pwm = + lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); + data->zone[i].limit = + lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); + data->zone[i].critical = + lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); + + if (IS_ADT7468_OFF64(data)) { + data->temp_min[i] -= 64; + data->temp_max[i] -= 64; + data->zone[i].limit -= 64; + data->zone[i].critical -= 64; + } + } + + if (data->type != emc6d103s) { + i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); + data->autofan[0].min_off = (i & 0x20) != 0; + data->autofan[1].min_off = (i & 0x40) != 0; + data->autofan[2].min_off = (i & 0x80) != 0; + + i = lm85_read_value(client, LM85_REG_AFAN_HYST1); + data->zone[0].hyst = i >> 4; + data->zone[1].hyst = i & 0x0f; + + i = lm85_read_value(client, LM85_REG_AFAN_HYST2); + data->zone[2].hyst = i >> 4; + } + + data->last_config = jiffies; + } /* last_config */ + + data->valid = 1; + + mutex_unlock(&data->update_lock); + + return data; +} /* 4 Fans */ static ssize_t show_fan(struct device *dev, struct device_attribute *attr, @@ -394,8 +585,8 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -460,6 +651,9 @@ static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, if (err) return err; + if (val > 255) + return -EINVAL; + data->vrm = val; return count; } @@ -515,8 +709,8 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -557,8 +751,8 @@ static ssize_t set_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 config; unsigned long val; int err; @@ -615,8 +809,8 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -682,8 +876,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -710,8 +904,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -766,8 +960,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -797,8 +991,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -843,8 +1037,8 @@ static ssize_t set_pwm_auto_channels(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -873,8 +1067,8 @@ static ssize_t set_pwm_auto_pwm_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -902,8 +1096,8 @@ static ssize_t set_pwm_auto_pwm_minctl(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 tmp; long val; int err; @@ -953,8 +1147,8 @@ static ssize_t set_temp_auto_temp_off(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int min; long val; int err; @@ -990,8 +1184,8 @@ static ssize_t set_temp_auto_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1029,8 +1223,8 @@ static ssize_t set_temp_auto_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int min; long val; int err; @@ -1063,8 +1257,8 @@ static ssize_t set_temp_auto_temp_crit(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); + struct lm85_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1355,30 +1549,18 @@ static int lm85_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } -static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data) -{ - sysfs_remove_group(&client->dev.kobj, &lm85_group); - if (data->type != emc6d103s) { - sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl); - sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off); - } - if (!data->has_vid5) - sysfs_remove_group(&client->dev.kobj, &lm85_group_in4); - if (data->type == emc6d100) - sysfs_remove_group(&client->dev.kobj, &lm85_group_in567); -} - -static int lm85_probe(struct i2c_client *client, - const struct i2c_device_id *id) +static int lm85_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct lm85_data *data; - int err; + int idx = 0; - data = devm_kzalloc(&client->dev, sizeof(struct lm85_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct lm85_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; data->type = id->driver_data; mutex_init(&data->update_lock); @@ -1403,20 +1585,13 @@ static int lm85_probe(struct i2c_client *client, /* Initialize the LM85 chip */ lm85_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &lm85_group); - if (err) - return err; + /* sysfs hooks */ + data->groups[idx++] = &lm85_group; /* minctl and temp_off exist on all chips except emc6d103s */ if (data->type != emc6d103s) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl); - if (err) - goto err_remove_files; - err = sysfs_create_group(&client->dev.kobj, - &lm85_group_temp_off); - if (err) - goto err_remove_files; + data->groups[idx++] = &lm85_group_minctl; + data->groups[idx++] = &lm85_group_temp_off; } /* @@ -1429,271 +1604,44 @@ static int lm85_probe(struct i2c_client *client, data->has_vid5 = true; } - if (!data->has_vid5) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_in4); - if (err) - goto err_remove_files; - } + if (!data->has_vid5) + data->groups[idx++] = &lm85_group_in4; /* The EMC6D100 has 3 additional voltage inputs */ - if (data->type == emc6d100) { - err = sysfs_create_group(&client->dev.kobj, &lm85_group_in567); - if (err) - goto err_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto err_remove_files; - } - - return 0; - - /* Error out and cleanup code */ - err_remove_files: - lm85_remove_files(client, data); - return err; -} - -static int lm85_remove(struct i2c_client *client) -{ - struct lm85_data *data = i2c_get_clientdata(client); - hwmon_device_unregister(data->hwmon_dev); - lm85_remove_files(client, data); - return 0; -} - - -static int lm85_read_value(struct i2c_client *client, u8 reg) -{ - int res; - - /* What size location is it? */ - switch (reg) { - case LM85_REG_FAN(0): /* Read WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - case LM85_REG_ALARM1: /* Read both bytes at once */ - res = i2c_smbus_read_byte_data(client, reg) & 0xff; - res |= i2c_smbus_read_byte_data(client, reg + 1) << 8; - break; - default: /* Read BYTE data */ - res = i2c_smbus_read_byte_data(client, reg); - break; - } - - return res; -} + if (data->type == emc6d100) + data->groups[idx++] = &lm85_group_in567; -static void lm85_write_value(struct i2c_client *client, u8 reg, int value) -{ - switch (reg) { - case LM85_REG_FAN(0): /* Write WORD data */ - case LM85_REG_FAN(1): - case LM85_REG_FAN(2): - case LM85_REG_FAN(3): - case LM85_REG_FAN_MIN(0): - case LM85_REG_FAN_MIN(1): - case LM85_REG_FAN_MIN(2): - case LM85_REG_FAN_MIN(3): - /* NOTE: ALARM is read only, so not included here */ - i2c_smbus_write_byte_data(client, reg, value & 0xff); - i2c_smbus_write_byte_data(client, reg + 1, value >> 8); - break; - default: /* Write BYTE data */ - i2c_smbus_write_byte_data(client, reg, value); - break; - } + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static struct lm85_data *lm85_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct lm85_data *data = i2c_get_clientdata(client); - int i; - - mutex_lock(&data->update_lock); - - if (!data->valid || - time_after(jiffies, data->last_reading + LM85_DATA_INTERVAL)) { - /* Things that change quickly */ - dev_dbg(&client->dev, "Reading sensor values\n"); - - /* - * Have to read extended bits first to "freeze" the - * more significant bits that are read later. - * There are 2 additional resolution bits per channel and we - * have room for 4, so we shift them to the left. - */ - if (data->type == adm1027 || data->type == adt7463 || - data->type == adt7468) { - int ext1 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - ADM1027_REG_EXTEND_ADC2); - int val = (ext1 << 8) + ext2; - - for (i = 0; i <= 4; i++) - data->in_ext[i] = - ((val >> (i * 2)) & 0x03) << 2; - - for (i = 0; i <= 2; i++) - data->temp_ext[i] = - (val >> ((i + 4) * 2)) & 0x0c; - } - - data->vid = lm85_read_value(client, LM85_REG_VID); - - for (i = 0; i <= 3; ++i) { - data->in[i] = - lm85_read_value(client, LM85_REG_IN(i)); - data->fan[i] = - lm85_read_value(client, LM85_REG_FAN(i)); - } - - if (!data->has_vid5) - data->in[4] = lm85_read_value(client, LM85_REG_IN(4)); - - if (data->type == adt7468) - data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5); - - for (i = 0; i <= 2; ++i) { - data->temp[i] = - lm85_read_value(client, LM85_REG_TEMP(i)); - data->pwm[i] = - lm85_read_value(client, LM85_REG_PWM(i)); - - if (IS_ADT7468_OFF64(data)) - data->temp[i] -= 64; - } - - data->alarms = lm85_read_value(client, LM85_REG_ALARM1); - - if (data->type == emc6d100) { - /* Three more voltage sensors */ - for (i = 5; i <= 7; ++i) { - data->in[i] = lm85_read_value(client, - EMC6D100_REG_IN(i)); - } - /* More alarm bits */ - data->alarms |= lm85_read_value(client, - EMC6D100_REG_ALARM3) << 16; - } else if (data->type == emc6d102 || data->type == emc6d103 || - data->type == emc6d103s) { - /* - * Have to read LSB bits after the MSB ones because - * the reading of the MSB bits has frozen the - * LSBs (backward from the ADM1027). - */ - int ext1 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC1); - int ext2 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC2); - int ext3 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC3); - int ext4 = lm85_read_value(client, - EMC6D102_REG_EXTEND_ADC4); - data->in_ext[0] = ext3 & 0x0f; - data->in_ext[1] = ext4 & 0x0f; - data->in_ext[2] = ext4 >> 4; - data->in_ext[3] = ext3 >> 4; - data->in_ext[4] = ext2 >> 4; - - data->temp_ext[0] = ext1 & 0x0f; - data->temp_ext[1] = ext2 & 0x0f; - data->temp_ext[2] = ext1 >> 4; - } - - data->last_reading = jiffies; - } /* last_reading */ - - if (!data->valid || - time_after(jiffies, data->last_config + LM85_CONFIG_INTERVAL)) { - /* Things that don't change often */ - dev_dbg(&client->dev, "Reading config values\n"); - - for (i = 0; i <= 3; ++i) { - data->in_min[i] = - lm85_read_value(client, LM85_REG_IN_MIN(i)); - data->in_max[i] = - lm85_read_value(client, LM85_REG_IN_MAX(i)); - data->fan_min[i] = - lm85_read_value(client, LM85_REG_FAN_MIN(i)); - } - - if (!data->has_vid5) { - data->in_min[4] = lm85_read_value(client, - LM85_REG_IN_MIN(4)); - data->in_max[4] = lm85_read_value(client, - LM85_REG_IN_MAX(4)); - } - - if (data->type == emc6d100) { - for (i = 5; i <= 7; ++i) { - data->in_min[i] = lm85_read_value(client, - EMC6D100_REG_IN_MIN(i)); - data->in_max[i] = lm85_read_value(client, - EMC6D100_REG_IN_MAX(i)); - } - } - - for (i = 0; i <= 2; ++i) { - int val; - - data->temp_min[i] = - lm85_read_value(client, LM85_REG_TEMP_MIN(i)); - data->temp_max[i] = - lm85_read_value(client, LM85_REG_TEMP_MAX(i)); - - data->autofan[i].config = - lm85_read_value(client, LM85_REG_AFAN_CONFIG(i)); - val = lm85_read_value(client, LM85_REG_AFAN_RANGE(i)); - data->pwm_freq[i] = val & 0x07; - data->zone[i].range = val >> 4; - data->autofan[i].min_pwm = - lm85_read_value(client, LM85_REG_AFAN_MINPWM(i)); - data->zone[i].limit = - lm85_read_value(client, LM85_REG_AFAN_LIMIT(i)); - data->zone[i].critical = - lm85_read_value(client, LM85_REG_AFAN_CRITICAL(i)); - - if (IS_ADT7468_OFF64(data)) { - data->temp_min[i] -= 64; - data->temp_max[i] -= 64; - data->zone[i].limit -= 64; - data->zone[i].critical -= 64; - } - } - - if (data->type != emc6d103s) { - i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1); - data->autofan[0].min_off = (i & 0x20) != 0; - data->autofan[1].min_off = (i & 0x40) != 0; - data->autofan[2].min_off = (i & 0x80) != 0; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST1); - data->zone[0].hyst = i >> 4; - data->zone[1].hyst = i & 0x0f; - - i = lm85_read_value(client, LM85_REG_AFAN_HYST2); - data->zone[2].hyst = i >> 4; - } - - data->last_config = jiffies; - } /* last_config */ - - data->valid = 1; - - mutex_unlock(&data->update_lock); +static const struct i2c_device_id lm85_id[] = { + { "adm1027", adm1027 }, + { "adt7463", adt7463 }, + { "adt7468", adt7468 }, + { "lm85", lm85 }, + { "lm85b", lm85 }, + { "lm85c", lm85 }, + { "emc6d100", emc6d100 }, + { "emc6d101", emc6d100 }, + { "emc6d102", emc6d102 }, + { "emc6d103", emc6d103 }, + { "emc6d103s", emc6d103s }, + { } +}; +MODULE_DEVICE_TABLE(i2c, lm85_id); - return data; -} +static struct i2c_driver lm85_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "lm85", + }, + .probe = lm85_probe, + .id_table = lm85_id, + .detect = lm85_detect, + .address_list = normal_i2c, +}; module_i2c_driver(lm85_driver); diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index 6c2df576f253..90bb04858117 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -207,7 +207,7 @@ struct block1_t { * Client-specific data */ struct lm93_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; unsigned long last_updated; /* In jiffies */ @@ -919,8 +919,8 @@ static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values) static struct lm93_data *lm93_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; const unsigned long interval = HZ + (HZ / 2); mutex_lock(&data->update_lock); @@ -1158,8 +1158,8 @@ static ssize_t store_in_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int vccp = nr - 6; long vid; unsigned long val; @@ -1239,8 +1239,8 @@ static ssize_t store_in_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int vccp = nr - 6; long vid; unsigned long val; @@ -1323,8 +1323,8 @@ static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1358,8 +1358,8 @@ static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1394,8 +1394,8 @@ static ssize_t store_temp_auto_base(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1430,8 +1430,8 @@ static ssize_t store_temp_auto_boost(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -1469,8 +1469,8 @@ static ssize_t store_temp_auto_boost_hyst(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -1520,8 +1520,8 @@ static ssize_t store_temp_auto_offset(struct device *dev, struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr); int nr = s_attr->index; int ofs = s_attr->nr; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -1632,8 +1632,8 @@ static ssize_t store_temp_auto_pwm_min(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 reg, ctl4; unsigned long val; int err; @@ -1680,8 +1680,8 @@ static ssize_t store_temp_auto_offset_hyst(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 reg; unsigned long val; int err; @@ -1741,8 +1741,8 @@ static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -1824,8 +1824,8 @@ static ssize_t store_fan_smart_tach(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -1880,8 +1880,8 @@ static ssize_t store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ctl2, ctl4; unsigned long val; int err; @@ -1928,8 +1928,8 @@ static ssize_t store_pwm_enable(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ctl2; unsigned long val; int err; @@ -2006,8 +2006,8 @@ static ssize_t store_pwm_freq(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ctl4; unsigned long val; int err; @@ -2046,8 +2046,8 @@ static ssize_t store_pwm_auto_channels(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -2087,8 +2087,8 @@ static ssize_t store_pwm_auto_spinup_min(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ctl3, ctl4; unsigned long val; int err; @@ -2130,8 +2130,8 @@ static ssize_t store_pwm_auto_spinup_time(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ctl3; unsigned long val; int err; @@ -2168,8 +2168,8 @@ static ssize_t store_pwm_auto_prochot_ramp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ramp; unsigned long val; int err; @@ -2202,8 +2202,8 @@ static ssize_t store_pwm_auto_vrdhot_ramp(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 ramp; unsigned long val; int err; @@ -2270,8 +2270,8 @@ static ssize_t store_prochot_max(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -2308,8 +2308,8 @@ static ssize_t store_prochot_override(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -2351,8 +2351,8 @@ static ssize_t store_prochot_interval(struct device *dev, const char *buf, size_t count) { int nr = (to_sensor_dev_attr(attr))->index; - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 tmp; unsigned long val; int err; @@ -2390,8 +2390,8 @@ static ssize_t store_prochot_override_duty_cycle(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -2423,8 +2423,8 @@ static ssize_t store_prochot_short(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct lm93_data *data = i2c_get_clientdata(client); + struct lm93_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -2631,9 +2631,7 @@ static struct attribute *lm93_attrs[] = { NULL }; -static struct attribute_group lm93_attr_grp = { - .attrs = lm93_attrs, -}; +ATTRIBUTE_GROUPS(lm93); static void lm93_init_client(struct i2c_client *client) { @@ -2726,61 +2724,42 @@ static int lm93_detect(struct i2c_client *client, struct i2c_board_info *info) static int lm93_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; struct lm93_data *data; - int err, func; + struct device *hwmon_dev; + int func; void (*update)(struct lm93_data *, struct i2c_client *); /* choose update routine based on bus capabilities */ func = i2c_get_functionality(client->adapter); if (((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) && (!disable_block)) { - dev_dbg(&client->dev, "using SMBus block data transactions\n"); + dev_dbg(dev, "using SMBus block data transactions\n"); update = lm93_update_client_full; } else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) { - dev_dbg(&client->dev, - "disabled SMBus block data transactions\n"); + dev_dbg(dev, "disabled SMBus block data transactions\n"); update = lm93_update_client_min; } else { - dev_dbg(&client->dev, - "detect failed, smbus byte and/or word data not supported!\n"); + dev_dbg(dev, "detect failed, smbus byte and/or word data not supported!\n"); return -ENODEV; } - data = devm_kzalloc(&client->dev, sizeof(struct lm93_data), GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct lm93_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); /* housekeeping */ + data->client = client; data->update = update; mutex_init(&data->update_lock); /* initialize the chip */ lm93_init_client(client); - err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp); - if (err) - return err; - - /* Register hwmon driver class */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (!IS_ERR(data->hwmon_dev)) - return 0; - - err = PTR_ERR(data->hwmon_dev); - dev_err(&client->dev, "error registering hwmon device.\n"); - sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); - return err; -} - -static int lm93_remove(struct i2c_client *client) -{ - struct lm93_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + lm93_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id lm93_id[] = { @@ -2796,7 +2775,6 @@ static struct i2c_driver lm93_driver = { .name = "lm93", }, .probe = lm93_probe, - .remove = lm93_remove, .id_table = lm93_id, .detect = lm93_detect, .address_list = normal_i2c, diff --git a/drivers/hwmon/ltc2945.c b/drivers/hwmon/ltc2945.c index 3701b329b6ae..1b92e4f6e234 100644 --- a/drivers/hwmon/ltc2945.c +++ b/drivers/hwmon/ltc2945.c @@ -469,7 +469,7 @@ static struct attribute *ltc2945_attrs[] = { }; ATTRIBUTE_GROUPS(ltc2945); -static struct regmap_config ltc2945_regmap_config = { +static const struct regmap_config ltc2945_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = LTC2945_MIN_ADIN_THRES_L, diff --git a/drivers/hwmon/ltc4222.c b/drivers/hwmon/ltc4222.c index 07c25653659f..88f747292816 100644 --- a/drivers/hwmon/ltc4222.c +++ b/drivers/hwmon/ltc4222.c @@ -186,7 +186,7 @@ static struct attribute *ltc4222_attrs[] = { }; ATTRIBUTE_GROUPS(ltc4222); -static struct regmap_config ltc4222_regmap_config = { +static const struct regmap_config ltc4222_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = LTC4222_ADC_CONTROL, diff --git a/drivers/hwmon/ltc4260.c b/drivers/hwmon/ltc4260.c index 453a250d9df5..afb09574b12c 100644 --- a/drivers/hwmon/ltc4260.c +++ b/drivers/hwmon/ltc4260.c @@ -150,7 +150,7 @@ static struct attribute *ltc4260_attrs[] = { }; ATTRIBUTE_GROUPS(ltc4260); -static struct regmap_config ltc4260_regmap_config = { +static const struct regmap_config ltc4260_regmap_config = { .reg_bits = 8, .val_bits = 8, .max_register = LTC4260_ADIN, diff --git a/drivers/hwmon/max16065.c b/drivers/hwmon/max16065.c index d4efc79d7b93..162401aaef71 100644 --- a/drivers/hwmon/max16065.c +++ b/drivers/hwmon/max16065.c @@ -642,10 +642,7 @@ static int max16065_probe(struct i2c_client *client, hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, data, data->groups); - if (unlikely(IS_ERR(hwmon_dev))) - return PTR_ERR(hwmon_dev); - - return 0; + return PTR_ERR_OR_ZERO(hwmon_dev); } static const struct i2c_device_id max16065_id[] = { diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c index e3ed0a5b6d94..7ca889910262 100644 --- a/drivers/hwmon/max1668.c +++ b/drivers/hwmon/max1668.c @@ -30,7 +30,7 @@ #include <linux/mutex.h> /* Addresses to scan */ -static unsigned short max1668_addr_list[] = { +static const unsigned short max1668_addr_list[] = { 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; /* max1668 registers */ diff --git a/drivers/hwmon/max6639.c b/drivers/hwmon/max6639.c index 70650de2cbd1..dac6d85f2fd9 100644 --- a/drivers/hwmon/max6639.c +++ b/drivers/hwmon/max6639.c @@ -35,7 +35,7 @@ #include <linux/i2c/max6639.h> /* Addresses to scan */ -static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; +static const unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END }; /* The MAX6639 registers, valid channel numbers: 0, 1 */ #define MAX6639_REG_TEMP(ch) (0x00 + (ch)) diff --git a/drivers/hwmon/max6697.c b/drivers/hwmon/max6697.c index 7fd3eaf817f4..f03a71722849 100644 --- a/drivers/hwmon/max6697.c +++ b/drivers/hwmon/max6697.c @@ -495,15 +495,13 @@ static void max6697_get_config_of(struct device_node *node, int len; const __be32 *prop; - prop = of_get_property(node, "smbus-timeout-disable", &len); - if (prop) - pdata->smbus_timeout_disable = true; - prop = of_get_property(node, "extended-range-enable", &len); - if (prop) - pdata->extended_range_enable = true; - prop = of_get_property(node, "beta-compensation-enable", &len); - if (prop) - pdata->beta_compensation = true; + pdata->smbus_timeout_disable = + of_property_read_bool(node, "smbus-timeout-disable"); + pdata->extended_range_enable = + of_property_read_bool(node, "extended-range-enable"); + pdata->beta_compensation = + of_property_read_bool(node, "beta-compensation-enable"); + prop = of_get_property(node, "alert-mask", &len); if (prop && len == sizeof(u32)) pdata->alert_mask = be32_to_cpu(prop[0]); diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index 59d9a3fc96b7..504cbddbdd90 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c @@ -735,7 +735,6 @@ struct nct6775_data { enum kinds kind; const char *name; - int num_attr_groups; const struct attribute_group *groups[6]; u16 reg_temp[5][NUM_TEMP]; /* 0=temp, 1=temp_over, 2=temp_hyst, @@ -3276,6 +3275,7 @@ static int nct6775_probe(struct platform_device *pdev) u8 cr2a; struct attribute_group *group; struct device *hwmon_dev; + int num_attr_groups = 0; res = platform_get_resource(pdev, IORESOURCE_IO, 0); if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, @@ -3907,29 +3907,29 @@ static int nct6775_probe(struct platform_device *pdev) if (IS_ERR(group)) return PTR_ERR(group); - data->groups[data->num_attr_groups++] = group; + data->groups[num_attr_groups++] = group; group = nct6775_create_attr_group(dev, &nct6775_in_template_group, fls(data->have_in)); if (IS_ERR(group)) return PTR_ERR(group); - data->groups[data->num_attr_groups++] = group; + data->groups[num_attr_groups++] = group; group = nct6775_create_attr_group(dev, &nct6775_fan_template_group, fls(data->has_fan)); if (IS_ERR(group)) return PTR_ERR(group); - data->groups[data->num_attr_groups++] = group; + data->groups[num_attr_groups++] = group; group = nct6775_create_attr_group(dev, &nct6775_temp_template_group, fls(data->have_temp)); if (IS_ERR(group)) return PTR_ERR(group); - data->groups[data->num_attr_groups++] = group; - data->groups[data->num_attr_groups++] = &nct6775_group_other; + data->groups[num_attr_groups++] = group; + data->groups[num_attr_groups++] = &nct6775_group_other; hwmon_dev = devm_hwmon_device_register_with_groups(dev, data->name, data, data->groups); @@ -4221,7 +4221,7 @@ static void __exit sensors_nct6775_exit(void) } MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); -MODULE_DESCRIPTION("NCT6775F/NCT6776F/NCT6779D driver"); +MODULE_DESCRIPTION("NCT6106D/NCT6775F/NCT6776F/NCT6779D/NCT6791D driver"); MODULE_LICENSE("GPL"); module_init(sensors_nct6775_init); diff --git a/drivers/hwmon/ntc_thermistor.c b/drivers/hwmon/ntc_thermistor.c index ae66f42c4d6d..bd410722cd4b 100644 --- a/drivers/hwmon/ntc_thermistor.c +++ b/drivers/hwmon/ntc_thermistor.c @@ -51,6 +51,7 @@ static const struct platform_device_id ntc_thermistor_id[] = { { "ncp21wb473", TYPE_NCPXXWB473 }, { "ncp03wb473", TYPE_NCPXXWB473 }, { "ncp15wl333", TYPE_NCPXXWL333 }, + { "b57330v2103", TYPE_B57330V2103}, { }, }; @@ -133,6 +134,47 @@ static const struct ntc_compensation ncpXXwl333[] = { { .temp_c = 125, .ohm = 707 }, }; +/* + * The following compensation table is from the specification of EPCOS NTC + * Thermistors Datasheet + */ +static const struct ntc_compensation b57330v2103[] = { + { .temp_c = -40, .ohm = 190030 }, + { .temp_c = -35, .ohm = 145360 }, + { .temp_c = -30, .ohm = 112060 }, + { .temp_c = -25, .ohm = 87041 }, + { .temp_c = -20, .ohm = 68104 }, + { .temp_c = -15, .ohm = 53665 }, + { .temp_c = -10, .ohm = 42576 }, + { .temp_c = -5, .ohm = 34001 }, + { .temp_c = 0, .ohm = 27326 }, + { .temp_c = 5, .ohm = 22096 }, + { .temp_c = 10, .ohm = 17973 }, + { .temp_c = 15, .ohm = 14703 }, + { .temp_c = 20, .ohm = 12090 }, + { .temp_c = 25, .ohm = 10000 }, + { .temp_c = 30, .ohm = 8311 }, + { .temp_c = 35, .ohm = 6941 }, + { .temp_c = 40, .ohm = 5825 }, + { .temp_c = 45, .ohm = 4911 }, + { .temp_c = 50, .ohm = 4158 }, + { .temp_c = 55, .ohm = 3536 }, + { .temp_c = 60, .ohm = 3019 }, + { .temp_c = 65, .ohm = 2588 }, + { .temp_c = 70, .ohm = 2227 }, + { .temp_c = 75, .ohm = 1924 }, + { .temp_c = 80, .ohm = 1668 }, + { .temp_c = 85, .ohm = 1451 }, + { .temp_c = 90, .ohm = 1266 }, + { .temp_c = 95, .ohm = 1108 }, + { .temp_c = 100, .ohm = 973 }, + { .temp_c = 105, .ohm = 857 }, + { .temp_c = 110, .ohm = 757 }, + { .temp_c = 115, .ohm = 671 }, + { .temp_c = 120, .ohm = 596 }, + { .temp_c = 125, .ohm = 531 }, +}; + struct ntc_data { struct device *hwmon_dev; struct ntc_thermistor_platform_data *pdata; @@ -173,6 +215,8 @@ static const struct of_device_id ntc_match[] = { .data = &ntc_thermistor_id[3] }, { .compatible = "murata,ncp15wl333", .data = &ntc_thermistor_id[4] }, + { .compatible = "epcos,b57330v2103", + .data = &ntc_thermistor_id[5]}, /* Usage of vendor name "ntc" is deprecated */ { .compatible = "ntc,ncp15wb473", @@ -490,6 +534,10 @@ static int ntc_thermistor_probe(struct platform_device *pdev) data->comp = ncpXXwl333; data->n_comp = ARRAY_SIZE(ncpXXwl333); break; + case TYPE_B57330V2103: + data->comp = b57330v2103; + data->n_comp = ARRAY_SIZE(b57330v2103); + break; default: dev_err(&pdev->dev, "Unknown device type: %lu(%s)\n", pdev_id->driver_data, pdev_id->name); @@ -546,7 +594,7 @@ static struct platform_driver ntc_thermistor_driver = { module_platform_driver(ntc_thermistor_driver); -MODULE_DESCRIPTION("NTC Thermistor Driver from Murata"); +MODULE_DESCRIPTION("NTC Thermistor Driver"); MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:ntc-thermistor"); diff --git a/drivers/hwmon/pmbus/Kconfig b/drivers/hwmon/pmbus/Kconfig index 39cc63edfbb0..6e1e4935fc62 100644 --- a/drivers/hwmon/pmbus/Kconfig +++ b/drivers/hwmon/pmbus/Kconfig @@ -20,8 +20,7 @@ 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, - MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, TPS40400, - and TPS40422. + MDT040, NCP4200, NCP4208, PDT003, PDT006, PDT012, UDT020, and TPS40400. This driver can also be built as a module. If so, the module will be called pmbus. @@ -87,6 +86,16 @@ config SENSORS_MAX8688 This driver can also be built as a module. If so, the module will be called max8688. +config SENSORS_TPS40422 + tristate "TI TPS40422" + default n + help + If you say yes here you get hardware monitoring support for TI + TPS40422. + + This driver can also be built as a module. If so, the module will + be called tps40422. + config SENSORS_UCD9000 tristate "TI UCD90120, UCD90124, UCD9090, UCD90910" default n diff --git a/drivers/hwmon/pmbus/Makefile b/drivers/hwmon/pmbus/Makefile index 789376c85dbb..1454293e985c 100644 --- a/drivers/hwmon/pmbus/Makefile +++ b/drivers/hwmon/pmbus/Makefile @@ -10,6 +10,7 @@ obj-$(CONFIG_SENSORS_LTC2978) += ltc2978.o obj-$(CONFIG_SENSORS_MAX16064) += max16064.o obj-$(CONFIG_SENSORS_MAX34440) += max34440.o obj-$(CONFIG_SENSORS_MAX8688) += max8688.o +obj-$(CONFIG_SENSORS_TPS40422) += tps40422.o obj-$(CONFIG_SENSORS_UCD9000) += ucd9000.o obj-$(CONFIG_SENSORS_UCD9200) += ucd9200.o obj-$(CONFIG_SENSORS_ZL6100) += zl6100.o diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c index 7e91700131a7..554d0249dcde 100644 --- a/drivers/hwmon/pmbus/pmbus.c +++ b/drivers/hwmon/pmbus/pmbus.c @@ -193,7 +193,6 @@ static const struct i2c_device_id pmbus_id[] = { {"pdt012", 1}, {"pmbus", 0}, {"tps40400", 1}, - {"tps40422", 2}, {"udt020", 1}, {} }; diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c new file mode 100644 index 000000000000..32803825d47e --- /dev/null +++ b/drivers/hwmon/pmbus/tps40422.c @@ -0,0 +1,64 @@ +/* + * Hardware monitoring driver for TI TPS40422 + * + * Copyright (c) 2014 Nokia Solutions and Networks. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/i2c.h> +#include "pmbus.h" + +static struct pmbus_driver_info tps40422_info = { + .pages = 2, + .format[PSC_VOLTAGE_IN] = linear, + .format[PSC_VOLTAGE_OUT] = linear, + .format[PSC_TEMPERATURE] = linear, + .func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, + .func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP2 + | PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP + | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT, +}; + +static int tps40422_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + return pmbus_do_probe(client, id, &tps40422_info); +} + +static const struct i2c_device_id tps40422_id[] = { + {"tps40422", 0}, + {} +}; + +MODULE_DEVICE_TABLE(i2c, tps40422_id); + +/* This is the driver that will be inserted */ +static struct i2c_driver tps40422_driver = { + .driver = { + .name = "tps40422", + }, + .probe = tps40422_probe, + .remove = pmbus_do_remove, + .id_table = tps40422_id, +}; + +module_i2c_driver(tps40422_driver); + +MODULE_AUTHOR("Zhu Laiwen <richard.zhu@nsn.com>"); +MODULE_DESCRIPTION("PMBus driver for TI TPS40422"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/powr1220.c b/drivers/hwmon/powr1220.c new file mode 100644 index 000000000000..3014e4ac741e --- /dev/null +++ b/drivers/hwmon/powr1220.c @@ -0,0 +1,391 @@ +/* + * powr1220.c - Driver for the Lattice POWR1220 programmable power supply + * and monitor. Users can read all ADC inputs along with their labels + * using the sysfs nodes. + * + * Copyright (c) 2014 Echo360 http://www.echo360.com + * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.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. + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/jiffies.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/delay.h> + +#define ADC_STEP_MV 2 +#define ADC_MAX_LOW_MEASUREMENT_MV 2000 + +enum powr1220_regs { + VMON_STATUS0, + VMON_STATUS1, + VMON_STATUS2, + OUTPUT_STATUS0, + OUTPUT_STATUS1, + OUTPUT_STATUS2, + INPUT_STATUS, + ADC_VALUE_LOW, + ADC_VALUE_HIGH, + ADC_MUX, + UES_BYTE0, + UES_BYTE1, + UES_BYTE2, + UES_BYTE3, + GP_OUTPUT1, + GP_OUTPUT2, + GP_OUTPUT3, + INPUT_VALUE, + RESET, + TRIM1_TRIM, + TRIM2_TRIM, + TRIM3_TRIM, + TRIM4_TRIM, + TRIM5_TRIM, + TRIM6_TRIM, + TRIM7_TRIM, + TRIM8_TRIM, + MAX_POWR1220_REGS +}; + +enum powr1220_adc_values { + VMON1, + VMON2, + VMON3, + VMON4, + VMON5, + VMON6, + VMON7, + VMON8, + VMON9, + VMON10, + VMON11, + VMON12, + VCCA, + VCCINP, + MAX_POWR1220_ADC_VALUES +}; + +struct powr1220_data { + struct i2c_client *client; + struct mutex update_lock; + bool adc_valid[MAX_POWR1220_ADC_VALUES]; + /* the next value is in jiffies */ + unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES]; + + /* values */ + int adc_maxes[MAX_POWR1220_ADC_VALUES]; + int adc_values[MAX_POWR1220_ADC_VALUES]; +}; + +static const char * const input_names[] = { + [VMON1] = "vmon1", + [VMON2] = "vmon2", + [VMON3] = "vmon3", + [VMON4] = "vmon4", + [VMON5] = "vmon5", + [VMON6] = "vmon6", + [VMON7] = "vmon7", + [VMON8] = "vmon8", + [VMON9] = "vmon9", + [VMON10] = "vmon10", + [VMON11] = "vmon11", + [VMON12] = "vmon12", + [VCCA] = "vcca", + [VCCINP] = "vccinp", +}; + +/* Reads the specified ADC channel */ +static int powr1220_read_adc(struct device *dev, int ch_num) +{ + struct powr1220_data *data = dev_get_drvdata(dev); + int reading; + int result; + int adc_range = 0; + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) || + !data->adc_valid[ch_num]) { + /* + * figure out if we need to use the attenuator for + * high inputs or inputs that we don't yet have a measurement + * for. We dynamically set the attenuator depending on the + * max reading. + */ + if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV || + data->adc_maxes[ch_num] == 0) + adc_range = 1 << 4; + + /* set the attenuator and mux */ + result = i2c_smbus_write_byte_data(data->client, ADC_MUX, + adc_range | ch_num); + if (result) + goto exit; + + /* + * wait at least Tconvert time (200 us) for the + * conversion to complete + */ + udelay(200); + + /* get the ADC reading */ + result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW); + if (result < 0) + goto exit; + + reading = result >> 4; + + /* get the upper half of the reading */ + result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH); + if (result < 0) + goto exit; + + reading |= result << 4; + + /* now convert the reading to a voltage */ + reading *= ADC_STEP_MV; + data->adc_values[ch_num] = reading; + data->adc_valid[ch_num] = true; + data->adc_last_updated[ch_num] = jiffies; + result = reading; + + if (reading > data->adc_maxes[ch_num]) + data->adc_maxes[ch_num] = reading; + } else { + result = data->adc_values[ch_num]; + } + +exit: + mutex_unlock(&data->update_lock); + + return result; +} + +/* Shows the voltage associated with the specified ADC channel */ +static ssize_t powr1220_show_voltage(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + int adc_val = powr1220_read_adc(dev, attr->index); + + if (adc_val < 0) + return adc_val; + + return sprintf(buf, "%d\n", adc_val); +} + +/* Shows the maximum setting associated with the specified ADC channel */ +static ssize_t powr1220_show_max(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + struct powr1220_data *data = dev_get_drvdata(dev); + + return sprintf(buf, "%d\n", data->adc_maxes[attr->index]); +} + +/* Shows the label associated with the specified ADC channel */ +static ssize_t powr1220_show_label(struct device *dev, + struct device_attribute *dev_attr, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr); + + return sprintf(buf, "%s\n", input_names[attr->index]); +} + +static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON1); +static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON2); +static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON3); +static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON4); +static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON5); +static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON6); +static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON7); +static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON8); +static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON9); +static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON10); +static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON11); +static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, powr1220_show_voltage, NULL, + VMON12); +static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, powr1220_show_voltage, NULL, + VCCA); +static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, powr1220_show_voltage, NULL, + VCCINP); + +static SENSOR_DEVICE_ATTR(in0_highest, S_IRUGO, powr1220_show_max, NULL, + VMON1); +static SENSOR_DEVICE_ATTR(in1_highest, S_IRUGO, powr1220_show_max, NULL, + VMON2); +static SENSOR_DEVICE_ATTR(in2_highest, S_IRUGO, powr1220_show_max, NULL, + VMON3); +static SENSOR_DEVICE_ATTR(in3_highest, S_IRUGO, powr1220_show_max, NULL, + VMON4); +static SENSOR_DEVICE_ATTR(in4_highest, S_IRUGO, powr1220_show_max, NULL, + VMON5); +static SENSOR_DEVICE_ATTR(in5_highest, S_IRUGO, powr1220_show_max, NULL, + VMON6); +static SENSOR_DEVICE_ATTR(in6_highest, S_IRUGO, powr1220_show_max, NULL, + VMON7); +static SENSOR_DEVICE_ATTR(in7_highest, S_IRUGO, powr1220_show_max, NULL, + VMON8); +static SENSOR_DEVICE_ATTR(in8_highest, S_IRUGO, powr1220_show_max, NULL, + VMON9); +static SENSOR_DEVICE_ATTR(in9_highest, S_IRUGO, powr1220_show_max, NULL, + VMON10); +static SENSOR_DEVICE_ATTR(in10_highest, S_IRUGO, powr1220_show_max, NULL, + VMON11); +static SENSOR_DEVICE_ATTR(in11_highest, S_IRUGO, powr1220_show_max, NULL, + VMON12); +static SENSOR_DEVICE_ATTR(in12_highest, S_IRUGO, powr1220_show_max, NULL, + VCCA); +static SENSOR_DEVICE_ATTR(in13_highest, S_IRUGO, powr1220_show_max, NULL, + VCCINP); + +static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, powr1220_show_label, NULL, + VMON1); +static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, powr1220_show_label, NULL, + VMON2); +static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, powr1220_show_label, NULL, + VMON3); +static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, powr1220_show_label, NULL, + VMON4); +static SENSOR_DEVICE_ATTR(in4_label, S_IRUGO, powr1220_show_label, NULL, + VMON5); +static SENSOR_DEVICE_ATTR(in5_label, S_IRUGO, powr1220_show_label, NULL, + VMON6); +static SENSOR_DEVICE_ATTR(in6_label, S_IRUGO, powr1220_show_label, NULL, + VMON7); +static SENSOR_DEVICE_ATTR(in7_label, S_IRUGO, powr1220_show_label, NULL, + VMON8); +static SENSOR_DEVICE_ATTR(in8_label, S_IRUGO, powr1220_show_label, NULL, + VMON9); +static SENSOR_DEVICE_ATTR(in9_label, S_IRUGO, powr1220_show_label, NULL, + VMON10); +static SENSOR_DEVICE_ATTR(in10_label, S_IRUGO, powr1220_show_label, NULL, + VMON11); +static SENSOR_DEVICE_ATTR(in11_label, S_IRUGO, powr1220_show_label, NULL, + VMON12); +static SENSOR_DEVICE_ATTR(in12_label, S_IRUGO, powr1220_show_label, NULL, + VCCA); +static SENSOR_DEVICE_ATTR(in13_label, S_IRUGO, powr1220_show_label, NULL, + VCCINP); + +static struct attribute *powr1220_attrs[] = { + &sensor_dev_attr_in0_input.dev_attr.attr, + &sensor_dev_attr_in1_input.dev_attr.attr, + &sensor_dev_attr_in2_input.dev_attr.attr, + &sensor_dev_attr_in3_input.dev_attr.attr, + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + &sensor_dev_attr_in8_input.dev_attr.attr, + &sensor_dev_attr_in9_input.dev_attr.attr, + &sensor_dev_attr_in10_input.dev_attr.attr, + &sensor_dev_attr_in11_input.dev_attr.attr, + &sensor_dev_attr_in12_input.dev_attr.attr, + &sensor_dev_attr_in13_input.dev_attr.attr, + + &sensor_dev_attr_in0_highest.dev_attr.attr, + &sensor_dev_attr_in1_highest.dev_attr.attr, + &sensor_dev_attr_in2_highest.dev_attr.attr, + &sensor_dev_attr_in3_highest.dev_attr.attr, + &sensor_dev_attr_in4_highest.dev_attr.attr, + &sensor_dev_attr_in5_highest.dev_attr.attr, + &sensor_dev_attr_in6_highest.dev_attr.attr, + &sensor_dev_attr_in7_highest.dev_attr.attr, + &sensor_dev_attr_in8_highest.dev_attr.attr, + &sensor_dev_attr_in9_highest.dev_attr.attr, + &sensor_dev_attr_in10_highest.dev_attr.attr, + &sensor_dev_attr_in11_highest.dev_attr.attr, + &sensor_dev_attr_in12_highest.dev_attr.attr, + &sensor_dev_attr_in13_highest.dev_attr.attr, + + &sensor_dev_attr_in0_label.dev_attr.attr, + &sensor_dev_attr_in1_label.dev_attr.attr, + &sensor_dev_attr_in2_label.dev_attr.attr, + &sensor_dev_attr_in3_label.dev_attr.attr, + &sensor_dev_attr_in4_label.dev_attr.attr, + &sensor_dev_attr_in5_label.dev_attr.attr, + &sensor_dev_attr_in6_label.dev_attr.attr, + &sensor_dev_attr_in7_label.dev_attr.attr, + &sensor_dev_attr_in8_label.dev_attr.attr, + &sensor_dev_attr_in9_label.dev_attr.attr, + &sensor_dev_attr_in10_label.dev_attr.attr, + &sensor_dev_attr_in11_label.dev_attr.attr, + &sensor_dev_attr_in12_label.dev_attr.attr, + &sensor_dev_attr_in13_label.dev_attr.attr, + + NULL +}; + +ATTRIBUTE_GROUPS(powr1220); + +static int powr1220_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct powr1220_data *data; + struct device *hwmon_dev; + + if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + mutex_init(&data->update_lock); + data->client = client; + + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, + client->name, data, powr1220_groups); + + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +static const struct i2c_device_id powr1220_ids[] = { + { "powr1220", 0, }, + { } +}; + +MODULE_DEVICE_TABLE(i2c, powr1220_ids); + +static struct i2c_driver powr1220_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "powr1220", + }, + .probe = powr1220_probe, + .id_table = powr1220_ids, +}; + +module_i2c_driver(powr1220_driver); + +MODULE_AUTHOR("Scott Kanowitz"); +MODULE_DESCRIPTION("POWR1220 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/pwm-fan.c b/drivers/hwmon/pwm-fan.c new file mode 100644 index 000000000000..823c877a1ec0 --- /dev/null +++ b/drivers/hwmon/pwm-fan.c @@ -0,0 +1,193 @@ +/* + * pwm-fan.c - Hwmon driver for fans connected to PWM lines. + * + * Copyright (c) 2014 Samsung Electronics Co., Ltd. + * + * Author: Kamil Debski <k.debski@samsung.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. + */ + +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/module.h> +#include <linux/mutex.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/pwm.h> +#include <linux/sysfs.h> + +#define MAX_PWM 255 + +struct pwm_fan_ctx { + struct mutex lock; + struct pwm_device *pwm; + unsigned char pwm_value; +}; + +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct pwm_fan_ctx *ctx = dev_get_drvdata(dev); + unsigned long pwm, duty; + ssize_t ret; + + if (kstrtoul(buf, 10, &pwm) || pwm > MAX_PWM) + return -EINVAL; + + mutex_lock(&ctx->lock); + + if (ctx->pwm_value == pwm) + goto exit_set_pwm_no_change; + + if (pwm == 0) { + pwm_disable(ctx->pwm); + goto exit_set_pwm; + } + + duty = DIV_ROUND_UP(pwm * (ctx->pwm->period - 1), MAX_PWM); + ret = pwm_config(ctx->pwm, duty, ctx->pwm->period); + if (ret) + goto exit_set_pwm_err; + + if (ctx->pwm_value == 0) { + ret = pwm_enable(ctx->pwm); + if (ret) + goto exit_set_pwm_err; + } + +exit_set_pwm: + ctx->pwm_value = pwm; +exit_set_pwm_no_change: + ret = count; +exit_set_pwm_err: + mutex_unlock(&ctx->lock); + return ret; +} + +static ssize_t show_pwm(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct pwm_fan_ctx *ctx = dev_get_drvdata(dev); + + return sprintf(buf, "%u\n", ctx->pwm_value); +} + + +static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_pwm, set_pwm, 0); + +static struct attribute *pwm_fan_attrs[] = { + &sensor_dev_attr_pwm1.dev_attr.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(pwm_fan); + +static int pwm_fan_probe(struct platform_device *pdev) +{ + struct device *hwmon; + struct pwm_fan_ctx *ctx; + int duty_cycle; + int ret; + + ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + mutex_init(&ctx->lock); + + ctx->pwm = devm_of_pwm_get(&pdev->dev, pdev->dev.of_node, NULL); + if (IS_ERR(ctx->pwm)) { + dev_err(&pdev->dev, "Could not get PWM\n"); + return PTR_ERR(ctx->pwm); + } + + platform_set_drvdata(pdev, ctx); + + /* Set duty cycle to maximum allowed */ + duty_cycle = ctx->pwm->period - 1; + ctx->pwm_value = MAX_PWM; + + ret = pwm_config(ctx->pwm, duty_cycle, ctx->pwm->period); + if (ret) { + dev_err(&pdev->dev, "Failed to configure PWM\n"); + return ret; + } + + /* Enbale PWM output */ + ret = pwm_enable(ctx->pwm); + if (ret) { + dev_err(&pdev->dev, "Failed to enable PWM\n"); + return ret; + } + + hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, "pwmfan", + ctx, pwm_fan_groups); + if (IS_ERR(hwmon)) { + dev_err(&pdev->dev, "Failed to register hwmon device\n"); + pwm_disable(ctx->pwm); + return PTR_ERR(hwmon); + } + return 0; +} + +static int pwm_fan_remove(struct platform_device *pdev) +{ + struct pwm_fan_ctx *ctx = platform_get_drvdata(pdev); + + if (ctx->pwm_value) + pwm_disable(ctx->pwm); + return 0; +} + +#ifdef CONFIG_PM_SLEEP +static int pwm_fan_suspend(struct device *dev) +{ + struct pwm_fan_ctx *ctx = dev_get_drvdata(dev); + + if (ctx->pwm_value) + pwm_disable(ctx->pwm); + return 0; +} + +static int pwm_fan_resume(struct device *dev) +{ + struct pwm_fan_ctx *ctx = dev_get_drvdata(dev); + + if (ctx->pwm_value) + return pwm_enable(ctx->pwm); + return 0; +} +#endif + +static SIMPLE_DEV_PM_OPS(pwm_fan_pm, pwm_fan_suspend, pwm_fan_resume); + +static struct of_device_id of_pwm_fan_match[] = { + { .compatible = "pwm-fan", }, + {}, +}; + +static struct platform_driver pwm_fan_driver = { + .probe = pwm_fan_probe, + .remove = pwm_fan_remove, + .driver = { + .name = "pwm-fan", + .pm = &pwm_fan_pm, + .of_match_table = of_pwm_fan_match, + }, +}; + +module_platform_driver(pwm_fan_driver); + +MODULE_AUTHOR("Kamil Debski <k.debski@samsung.com>"); +MODULE_ALIAS("platform:pwm-fan"); +MODULE_DESCRIPTION("PWM FAN driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 2e9f9570b6f8..84cdb1cf0fb4 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -45,7 +45,7 @@ * @humidity: cached humidity measurement value */ struct sht21 { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex lock; char valid; unsigned long last_update; @@ -85,14 +85,15 @@ static inline int sht21_rh_ticks_to_per_cent_mille(int ticks) /** * sht21_update_measurements() - get updated measurements from device - * @client: I2C client device + * @dev: device * * Returns 0 on success, else negative errno. */ -static int sht21_update_measurements(struct i2c_client *client) +static int sht21_update_measurements(struct device *dev) { int ret = 0; - struct sht21 *sht21 = i2c_get_clientdata(client); + struct sht21 *sht21 = dev_get_drvdata(dev); + struct i2c_client *client = sht21->client; mutex_lock(&sht21->lock); /* @@ -133,9 +134,10 @@ static ssize_t sht21_show_temperature(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct sht21 *sht21 = i2c_get_clientdata(client); - int ret = sht21_update_measurements(client); + struct sht21 *sht21 = dev_get_drvdata(dev); + int ret; + + ret = sht21_update_measurements(dev); if (ret < 0) return ret; return sprintf(buf, "%d\n", sht21->temperature); @@ -154,9 +156,10 @@ static ssize_t sht21_show_humidity(struct device *dev, struct device_attribute *attr, char *buf) { - struct i2c_client *client = to_i2c_client(dev); - struct sht21 *sht21 = i2c_get_clientdata(client); - int ret = sht21_update_measurements(client); + struct sht21 *sht21 = dev_get_drvdata(dev); + int ret; + + ret = sht21_update_measurements(dev); if (ret < 0) return ret; return sprintf(buf, "%d\n", sht21->humidity); @@ -168,30 +171,20 @@ static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, sht21_show_temperature, static SENSOR_DEVICE_ATTR(humidity1_input, S_IRUGO, sht21_show_humidity, NULL, 0); -static struct attribute *sht21_attributes[] = { +static struct attribute *sht21_attrs[] = { &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_humidity1_input.dev_attr.attr, NULL }; -static const struct attribute_group sht21_attr_group = { - .attrs = sht21_attributes, -}; +ATTRIBUTE_GROUPS(sht21); -/** - * sht21_probe() - probe device - * @client: I2C client device - * @id: device ID - * - * Called by the I2C core when an entry in the ID table matches a - * device's name. - * Returns 0 on success. - */ static int sht21_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct sht21 *sht21; - int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WORD_DATA)) { @@ -200,47 +193,17 @@ static int sht21_probe(struct i2c_client *client, return -ENODEV; } - sht21 = devm_kzalloc(&client->dev, sizeof(*sht21), GFP_KERNEL); + sht21 = devm_kzalloc(dev, sizeof(*sht21), GFP_KERNEL); if (!sht21) return -ENOMEM; - i2c_set_clientdata(client, sht21); + sht21->client = client; mutex_init(&sht21->lock); - err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group); - if (err) { - dev_dbg(&client->dev, "could not create sysfs files\n"); - return err; - } - sht21->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(sht21->hwmon_dev)) { - dev_dbg(&client->dev, "unable to register hwmon device\n"); - err = PTR_ERR(sht21->hwmon_dev); - goto fail_remove_sysfs; - } - - dev_info(&client->dev, "initialized\n"); - - return 0; - -fail_remove_sysfs: - sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); - return err; -} - -/** - * sht21_remove() - remove device - * @client: I2C client device - */ -static int sht21_remove(struct i2c_client *client) -{ - struct sht21 *sht21 = i2c_get_clientdata(client); - - hwmon_device_unregister(sht21->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + sht21, sht21_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } /* Device ID table */ @@ -253,7 +216,6 @@ MODULE_DEVICE_TABLE(i2c, sht21_id); static struct i2c_driver sht21_driver = { .driver.name = "sht21", .probe = sht21_probe, - .remove = sht21_remove, .id_table = sht21_id, }; diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c index 3532026e25da..bf1d7893d51c 100644 --- a/drivers/hwmon/sis5595.c +++ b/drivers/hwmon/sis5595.c @@ -159,7 +159,7 @@ static inline int TEMP_FROM_REG(s8 val) { return val * 830 + 52120; } -static inline s8 TEMP_TO_REG(int val) +static inline s8 TEMP_TO_REG(long val) { int nval = clamp_val(val, -54120, 157530) ; return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830; diff --git a/drivers/hwmon/smm665.c b/drivers/hwmon/smm665.c index 4ef5802df6d8..627c9c3a8255 100644 --- a/drivers/hwmon/smm665.c +++ b/drivers/hwmon/smm665.c @@ -140,7 +140,7 @@ enum chips { smm465, smm665, smm665c, smm764, smm766 }; struct smm665_data { enum chips type; int conversion_time; /* ADC conversion time */ - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; bool valid; unsigned long last_updated; /* in jiffies */ @@ -239,8 +239,8 @@ static int smm665_read_adc(struct smm665_data *data, int adc) static struct smm665_data *smm665_update_device(struct device *dev) { - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); + struct smm665_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; struct smm665_data *ret = data; mutex_lock(&data->update_lock); @@ -315,32 +315,28 @@ static int smm665_convert(u16 adcval, int index) static int smm665_get_min(struct device *dev, int index) { - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); + struct smm665_data *data = dev_get_drvdata(dev); return data->alarm_min_limit[index]; } static int smm665_get_max(struct device *dev, int index) { - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); + struct smm665_data *data = dev_get_drvdata(dev); return data->alarm_max_limit[index]; } static int smm665_get_lcrit(struct device *dev, int index) { - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); + struct smm665_data *data = dev_get_drvdata(dev); return data->critical_min_limit[index]; } static int smm665_get_crit(struct device *dev, int index) { - struct i2c_client *client = to_i2c_client(dev); - struct smm665_data *data = i2c_get_clientdata(client); + struct smm665_data *data = dev_get_drvdata(dev); return data->critical_max_limit[index]; } @@ -486,7 +482,7 @@ SMM665_ATTR(temp1, crit_alarm, SMM665_FAULT_TEMP); * Finally, construct an array of pointers to members of the above objects, * as required for sysfs_create_group() */ -static struct attribute *smm665_attributes[] = { +static struct attribute *smm665_attrs[] = { &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in1_min.dev_attr.attr, &sensor_dev_attr_in1_max.dev_attr.attr, @@ -567,15 +563,14 @@ static struct attribute *smm665_attributes[] = { NULL, }; -static const struct attribute_group smm665_group = { - .attrs = smm665_attributes, -}; +ATTRIBUTE_GROUPS(smm665); static int smm665_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct i2c_adapter *adapter = client->adapter; struct smm665_data *data; + struct device *hwmon_dev; int i, ret; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA @@ -592,6 +587,7 @@ static int smm665_probe(struct i2c_client *client, i2c_set_clientdata(client, data); mutex_init(&data->update_lock); + data->client = client; data->type = id->driver_data; data->cmdreg = i2c_new_dummy(adapter, (client->addr & ~SMM665_REGMASK) | SMM665_CMDREG_BASE); @@ -662,21 +658,16 @@ static int smm665_probe(struct i2c_client *client, data->alarm_max_limit[i] = smm665_convert(val, i); } - /* Register sysfs hooks */ - ret = sysfs_create_group(&client->dev.kobj, &smm665_group); - if (ret) + hwmon_dev = devm_hwmon_device_register_with_groups(&client->dev, + client->name, data, + smm665_groups); + if (IS_ERR(hwmon_dev)) { + ret = PTR_ERR(hwmon_dev); goto out_unregister; - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - ret = PTR_ERR(data->hwmon_dev); - goto out_remove_group; } return 0; -out_remove_group: - sysfs_remove_group(&client->dev.kobj, &smm665_group); out_unregister: i2c_unregister_device(data->cmdreg); return ret; @@ -687,9 +678,6 @@ static int smm665_remove(struct i2c_client *client) struct smm665_data *data = i2c_get_clientdata(client); i2c_unregister_device(data->cmdreg); - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &smm665_group); - return 0; } diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c index 23a22c4eee51..d7485659acc5 100644 --- a/drivers/hwmon/smsc47m1.c +++ b/drivers/hwmon/smsc47m1.c @@ -142,11 +142,6 @@ struct smsc47m1_sio_data { u8 activate; /* Remember initial device state */ }; - -static int __exit smsc47m1_remove(struct platform_device *pdev); -static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, - int init); - static inline int smsc47m1_read_value(struct smsc47m1_data *data, u8 reg) { return inb_p(data->addr + reg); @@ -158,13 +153,54 @@ static inline void smsc47m1_write_value(struct smsc47m1_data *data, u8 reg, outb_p(value, data->addr + reg); } -static struct platform_driver smsc47m1_driver = { - .driver = { - .owner = THIS_MODULE, - .name = DRVNAME, - }, - .remove = __exit_p(smsc47m1_remove), -}; +static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, + int init) +{ + struct smsc47m1_data *data = dev_get_drvdata(dev); + + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { + int i, fan_nr; + fan_nr = data->type == smsc47m2 ? 3 : 2; + + for (i = 0; i < fan_nr; i++) { + data->fan[i] = smsc47m1_read_value(data, + SMSC47M1_REG_FAN[i]); + data->fan_preload[i] = smsc47m1_read_value(data, + SMSC47M1_REG_FAN_PRELOAD[i]); + data->pwm[i] = smsc47m1_read_value(data, + SMSC47M1_REG_PWM[i]); + } + + i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV); + data->fan_div[0] = (i >> 4) & 0x03; + data->fan_div[1] = i >> 6; + + data->alarms = smsc47m1_read_value(data, + SMSC47M1_REG_ALARM) >> 6; + /* Clear alarms if needed */ + if (data->alarms) + smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0); + + if (fan_nr >= 3) { + data->fan_div[2] = (smsc47m1_read_value(data, + SMSC47M2_REG_FANDIV3) >> 4) & 0x03; + data->alarms |= (smsc47m1_read_value(data, + SMSC47M2_REG_ALARM6) & 0x40) >> 4; + /* Clear alarm if needed */ + if (data->alarms & 0x04) + smsc47m1_write_value(data, + SMSC47M2_REG_ALARM6, + 0x40); + } + + data->last_updated = jiffies; + } + + mutex_unlock(&data->update_lock); + return data; +} static ssize_t get_fan(struct device *dev, struct device_attribute *devattr, char *buf) @@ -811,54 +847,13 @@ static int __exit smsc47m1_remove(struct platform_device *pdev) return 0; } -static struct smsc47m1_data *smsc47m1_update_device(struct device *dev, - int init) -{ - struct smsc47m1_data *data = dev_get_drvdata(dev); - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) || init) { - int i, fan_nr; - fan_nr = data->type == smsc47m2 ? 3 : 2; - - for (i = 0; i < fan_nr; i++) { - data->fan[i] = smsc47m1_read_value(data, - SMSC47M1_REG_FAN[i]); - data->fan_preload[i] = smsc47m1_read_value(data, - SMSC47M1_REG_FAN_PRELOAD[i]); - data->pwm[i] = smsc47m1_read_value(data, - SMSC47M1_REG_PWM[i]); - } - - i = smsc47m1_read_value(data, SMSC47M1_REG_FANDIV); - data->fan_div[0] = (i >> 4) & 0x03; - data->fan_div[1] = i >> 6; - - data->alarms = smsc47m1_read_value(data, - SMSC47M1_REG_ALARM) >> 6; - /* Clear alarms if needed */ - if (data->alarms) - smsc47m1_write_value(data, SMSC47M1_REG_ALARM, 0xC0); - - if (fan_nr >= 3) { - data->fan_div[2] = (smsc47m1_read_value(data, - SMSC47M2_REG_FANDIV3) >> 4) & 0x03; - data->alarms |= (smsc47m1_read_value(data, - SMSC47M2_REG_ALARM6) & 0x40) >> 4; - /* Clear alarm if needed */ - if (data->alarms & 0x04) - smsc47m1_write_value(data, - SMSC47M2_REG_ALARM6, - 0x40); - } - - data->last_updated = jiffies; - } - - mutex_unlock(&data->update_lock); - return data; -} +static struct platform_driver smsc47m1_driver = { + .driver = { + .owner = THIS_MODULE, + .name = DRVNAME, + }, + .remove = __exit_p(smsc47m1_remove), +}; static int __init smsc47m1_device_add(unsigned short address, const struct smsc47m1_sio_data *sio_data) diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c index 34b9a601ad07..6ac7cda72d4c 100644 --- a/drivers/hwmon/smsc47m192.c +++ b/drivers/hwmon/smsc47m192.c @@ -95,7 +95,8 @@ static inline int TEMP_FROM_REG(s8 val) } struct smsc47m192_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -112,30 +113,69 @@ struct smsc47m192_data { u8 vrm; }; -static int smsc47m192_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int smsc47m192_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int smsc47m192_remove(struct i2c_client *client); -static struct smsc47m192_data *smsc47m192_update_device(struct device *dev); +static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) +{ + struct smsc47m192_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i, config; -static const struct i2c_device_id smsc47m192_id[] = { - { "smsc47m192", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, smsc47m192_id); + mutex_lock(&data->update_lock); -static struct i2c_driver smsc47m192_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "smsc47m192", - }, - .probe = smsc47m192_probe, - .remove = smsc47m192_remove, - .id_table = smsc47m192_id, - .detect = smsc47m192_detect, - .address_list = normal_i2c, -}; + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); + + dev_dbg(&client->dev, "Starting smsc47m192 update\n"); + + for (i = 0; i <= 7; i++) { + data->in[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN(i)); + data->in_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MIN(i)); + data->in_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_IN_MAX(i)); + } + for (i = 0; i < 3; i++) { + data->temp[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_MIN[i]); + } + for (i = 1; i < 3; i++) + data->temp_offset[i] = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_TEMP_OFFSET(i)); + /* + * first offset is temp_offset[0] if SFR bit 4 is set, + * temp_offset[1] otherwise + */ + if (sfr & 0x10) { + data->temp_offset[0] = data->temp_offset[1]; + data->temp_offset[1] = 0; + } else + data->temp_offset[0] = 0; + + data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) + & 0x0f; + config = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_CONFIG); + if (config & 0x20) + data->vid |= (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_VID4) & 0x01) << 4; + data->alarms = i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM1) | + (i2c_smbus_read_byte_data(client, + SMSC47M192_REG_ALARM2) << 8); + + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} /* Voltages */ static ssize_t show_in(struct device *dev, struct device_attribute *attr, @@ -170,8 +210,8 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); + struct smsc47m192_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -192,8 +232,8 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); + struct smsc47m192_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -259,8 +299,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); + struct smsc47m192_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -281,8 +321,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); + struct smsc47m192_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -312,8 +352,8 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute { struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); int nr = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); + struct smsc47m192_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); long val; int err; @@ -552,124 +592,50 @@ static int smsc47m192_detect(struct i2c_client *client, static int smsc47m192_probe(struct i2c_client *client, const struct i2c_device_id *id) { + struct device *dev = &client->dev; + struct device *hwmon_dev; struct smsc47m192_data *data; int config; - int err; - data = devm_kzalloc(&client->dev, sizeof(struct smsc47m192_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct smsc47m192_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; data->vrm = vid_which_vrm(); mutex_init(&data->update_lock); /* Initialize the SMSC47M192 chip */ smsc47m192_init_client(client); - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &smsc47m192_group); - if (err) - return err; - + /* sysfs hooks */ + data->groups[0] = &smsc47m192_group; /* Pin 110 is either in4 (+12V) or VID4 */ config = i2c_smbus_read_byte_data(client, SMSC47M192_REG_CONFIG); - if (!(config & 0x20)) { - err = sysfs_create_group(&client->dev.kobj, - &smsc47m192_group_in4); - if (err) - goto exit_remove_files; - } - - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_files; - } - - return 0; - -exit_remove_files: - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); - return err; -} - -static int smsc47m192_remove(struct i2c_client *client) -{ - struct smsc47m192_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group); - sysfs_remove_group(&client->dev.kobj, &smsc47m192_group_in4); + if (!(config & 0x20)) + data->groups[1] = &smsc47m192_group_in4; - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static struct smsc47m192_data *smsc47m192_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct smsc47m192_data *data = i2c_get_clientdata(client); - int i, config; - - mutex_lock(&data->update_lock); - - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR); - - dev_dbg(&client->dev, "Starting smsc47m192 update\n"); - - for (i = 0; i <= 7; i++) { - data->in[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_IN(i)); - data->in_min[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_IN_MIN(i)); - data->in_max[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_IN_MAX(i)); - } - for (i = 0; i < 3; i++) { - data->temp[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP[i]); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP_MAX[i]); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP_MIN[i]); - } - for (i = 1; i < 3; i++) - data->temp_offset[i] = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_TEMP_OFFSET(i)); - /* - * first offset is temp_offset[0] if SFR bit 4 is set, - * temp_offset[1] otherwise - */ - if (sfr & 0x10) { - data->temp_offset[0] = data->temp_offset[1]; - data->temp_offset[1] = 0; - } else - data->temp_offset[0] = 0; - - data->vid = i2c_smbus_read_byte_data(client, SMSC47M192_REG_VID) - & 0x0f; - config = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_CONFIG); - if (config & 0x20) - data->vid |= (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_VID4) & 0x01) << 4; - data->alarms = i2c_smbus_read_byte_data(client, - SMSC47M192_REG_ALARM1) | - (i2c_smbus_read_byte_data(client, - SMSC47M192_REG_ALARM2) << 8); - - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); +static const struct i2c_device_id smsc47m192_id[] = { + { "smsc47m192", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, smsc47m192_id); - return data; -} +static struct i2c_driver smsc47m192_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "smsc47m192", + }, + .probe = smsc47m192_probe, + .id_table = smsc47m192_id, + .detect = smsc47m192_detect, + .address_list = normal_i2c, +}; module_i2c_driver(smsc47m192_driver); diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c index db288db7d3e9..6a0ee903127e 100644 --- a/drivers/hwmon/thmc50.c +++ b/drivers/hwmon/thmc50.c @@ -68,7 +68,8 @@ static const u8 THMC50_REG_TEMP_DEFAULT[] = { 0x17, 0x18, 0x18 }; /* Each client has this additional data */ struct thmc50_data { - struct device *hwmon_dev; + struct i2c_client *client; + const struct attribute_group *groups[3]; struct mutex update_lock; enum chips type; @@ -85,32 +86,47 @@ struct thmc50_data { u8 alarms; }; -static int thmc50_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int thmc50_remove(struct i2c_client *client); -static void thmc50_init_client(struct i2c_client *client); -static struct thmc50_data *thmc50_update_device(struct device *dev); +static struct thmc50_data *thmc50_update_device(struct device *dev) +{ + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); -static const struct i2c_device_id thmc50_id[] = { - { "adm1022", adm1022 }, - { "thmc50", thmc50 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, thmc50_id); + mutex_lock(&data->update_lock); -static struct i2c_driver thmc50_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "thmc50", - }, - .probe = thmc50_probe, - .remove = thmc50_remove, - .id_table = thmc50_id, - .detect = thmc50_detect, - .address_list = normal_i2c, -}; + if (time_after(jiffies, data->last_updated + timeout) + || !data->valid) { + + int temps = data->has_temp3 ? 3 : 2; + int i; + int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + + prog &= THMC50_REG_CONF_PROGRAMMED; + + for (i = 0; i < temps; i++) { + data->temp_input[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP[i]); + data->temp_max[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP_MAX[i]); + data->temp_min[i] = i2c_smbus_read_byte_data(client, + THMC50_REG_TEMP_MIN[i]); + data->temp_critical[i] = + i2c_smbus_read_byte_data(client, + prog ? THMC50_REG_TEMP_CRITICAL[i] + : THMC50_REG_TEMP_DEFAULT[i]); + } + data->analog_out = + i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); + data->alarms = + i2c_smbus_read_byte_data(client, THMC50_REG_INTR); + data->last_updated = jiffies; + data->valid = 1; + } + + mutex_unlock(&data->update_lock); + + return data; +} static ssize_t show_analog_out(struct device *dev, struct device_attribute *attr, char *buf) @@ -123,8 +139,8 @@ static ssize_t set_analog_out(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; int config; unsigned long tmp; int err; @@ -177,8 +193,8 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -206,8 +222,8 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); + struct thmc50_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -355,67 +371,9 @@ static int thmc50_detect(struct i2c_client *client, return 0; } -static int thmc50_probe(struct i2c_client *client, - const struct i2c_device_id *id) -{ - struct thmc50_data *data; - int err; - - data = devm_kzalloc(&client->dev, sizeof(struct thmc50_data), - GFP_KERNEL); - if (!data) - return -ENOMEM; - - i2c_set_clientdata(client, data); - data->type = id->driver_data; - mutex_init(&data->update_lock); - - thmc50_init_client(client); - - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &thmc50_group); - if (err) - return err; - - /* Register ADM1022 sysfs hooks */ - if (data->has_temp3) { - err = sysfs_create_group(&client->dev.kobj, &temp3_group); - if (err) - goto exit_remove_sysfs_thmc50; - } - - /* Register a new directory entry with module sensors */ - data->hwmon_dev = hwmon_device_register(&client->dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove_sysfs; - } - - return 0; - -exit_remove_sysfs: - if (data->has_temp3) - sysfs_remove_group(&client->dev.kobj, &temp3_group); -exit_remove_sysfs_thmc50: - sysfs_remove_group(&client->dev.kobj, &thmc50_group); - return err; -} - -static int thmc50_remove(struct i2c_client *client) +static void thmc50_init_client(struct thmc50_data *data) { - struct thmc50_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &thmc50_group); - if (data->has_temp3) - sysfs_remove_group(&client->dev.kobj, &temp3_group); - - return 0; -} - -static void thmc50_init_client(struct i2c_client *client) -{ - struct thmc50_data *data = i2c_get_clientdata(client); + struct i2c_client *client = data->client; int config; data->analog_out = i2c_smbus_read_byte_data(client, @@ -433,48 +391,54 @@ static void thmc50_init_client(struct i2c_client *client) i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config); } -static struct thmc50_data *thmc50_update_device(struct device *dev) +static int thmc50_probe(struct i2c_client *client, + const struct i2c_device_id *id) { - struct i2c_client *client = to_i2c_client(dev); - struct thmc50_data *data = i2c_get_clientdata(client); - int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0); + struct device *dev = &client->dev; + struct thmc50_data *data; + struct device *hwmon_dev; + int idx = 0; - mutex_lock(&data->update_lock); + data = devm_kzalloc(dev, sizeof(struct thmc50_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - if (time_after(jiffies, data->last_updated + timeout) - || !data->valid) { + data->client = client; + data->type = id->driver_data; + mutex_init(&data->update_lock); - int temps = data->has_temp3 ? 3 : 2; - int i; - int prog = i2c_smbus_read_byte_data(client, THMC50_REG_CONF); + thmc50_init_client(data); - prog &= THMC50_REG_CONF_PROGRAMMED; + /* sysfs hooks */ + data->groups[idx++] = &thmc50_group; - for (i = 0; i < temps; i++) { - data->temp_input[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP[i]); - data->temp_max[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP_MAX[i]); - data->temp_min[i] = i2c_smbus_read_byte_data(client, - THMC50_REG_TEMP_MIN[i]); - data->temp_critical[i] = - i2c_smbus_read_byte_data(client, - prog ? THMC50_REG_TEMP_CRITICAL[i] - : THMC50_REG_TEMP_DEFAULT[i]); - } - data->analog_out = - i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT); - data->alarms = - i2c_smbus_read_byte_data(client, THMC50_REG_INTR); - data->last_updated = jiffies; - data->valid = 1; - } - - mutex_unlock(&data->update_lock); + /* Register additional ADM1022 sysfs hooks */ + if (data->has_temp3) + data->groups[idx++] = &temp3_group; - return data; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, data->groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } +static const struct i2c_device_id thmc50_id[] = { + { "adm1022", adm1022 }, + { "thmc50", thmc50 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, thmc50_id); + +static struct i2c_driver thmc50_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "thmc50", + }, + .probe = thmc50_probe, + .id_table = thmc50_id, + .detect = thmc50_detect, + .address_list = normal_i2c, +}; + module_i2c_driver(thmc50_driver); MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>"); diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c new file mode 100644 index 000000000000..c74d2da389d9 --- /dev/null +++ b/drivers/hwmon/tmp103.c @@ -0,0 +1,206 @@ +/* + * Texas Instruments TMP103 SMBus temperature sensor driver + * Copyright (C) 2014 Heiko Schocher <hs@denx.de> + * + * Based on: + * Texas Instruments TMP102 SMBus temperature sensor driver + * + * Copyright (C) 2010 Steven King <sfking@fdwdc.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. + * + */ + +#include <linux/module.h> +#include <linux/init.h> +#include <linux/slab.h> +#include <linux/i2c.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/err.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/jiffies.h> +#include <linux/regmap.h> + +#define TMP103_TEMP_REG 0x00 +#define TMP103_CONF_REG 0x01 +#define TMP103_TLOW_REG 0x02 +#define TMP103_THIGH_REG 0x03 + +#define TMP103_CONF_M0 0x01 +#define TMP103_CONF_M1 0x02 +#define TMP103_CONF_LC 0x04 +#define TMP103_CONF_FL 0x08 +#define TMP103_CONF_FH 0x10 +#define TMP103_CONF_CR0 0x20 +#define TMP103_CONF_CR1 0x40 +#define TMP103_CONF_ID 0x80 +#define TMP103_CONF_SD (TMP103_CONF_M1) +#define TMP103_CONF_SD_MASK (TMP103_CONF_M0 | TMP103_CONF_M1) + +#define TMP103_CONFIG (TMP103_CONF_CR1 | TMP103_CONF_M1) +#define TMP103_CONFIG_MASK (TMP103_CONF_CR0 | TMP103_CONF_CR1 | \ + TMP103_CONF_M0 | TMP103_CONF_M1) + +static inline int tmp103_reg_to_mc(s8 val) +{ + return val * 1000; +} + +static inline u8 tmp103_mc_to_reg(int val) +{ + return DIV_ROUND_CLOSEST(val, 1000); +} + +static ssize_t tmp103_show_temp(struct device *dev, + struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct regmap *regmap = dev_get_drvdata(dev); + unsigned int regval; + int ret; + + ret = regmap_read(regmap, sda->index, ®val); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", tmp103_reg_to_mc(regval)); +} + +static ssize_t tmp103_set_temp(struct device *dev, + struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); + struct regmap *regmap = dev_get_drvdata(dev); + long val; + int ret; + + if (kstrtol(buf, 10, &val) < 0) + return -EINVAL; + + val = clamp_val(val, -55000, 127000); + ret = regmap_write(regmap, sda->index, tmp103_mc_to_reg(val)); + return ret ? ret : count; +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, tmp103_show_temp, NULL , + TMP103_TEMP_REG); + +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, tmp103_show_temp, + tmp103_set_temp, TMP103_TLOW_REG); + +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp103_show_temp, + tmp103_set_temp, TMP103_THIGH_REG); + +static struct attribute *tmp103_attrs[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + NULL +}; +ATTRIBUTE_GROUPS(tmp103); + +static bool tmp103_regmap_is_volatile(struct device *dev, unsigned int reg) +{ + return reg == TMP103_TEMP_REG; +} + +static const struct regmap_config tmp103_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = TMP103_THIGH_REG, + .volatile_reg = tmp103_regmap_is_volatile, +}; + +static int tmp103_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct device *dev = &client->dev; + struct device *hwmon_dev; + struct regmap *regmap; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA)) { + dev_err(&client->dev, + "adapter doesn't support SMBus byte transactions\n"); + return -ENODEV; + } + + regmap = devm_regmap_init_i2c(client, &tmp103_regmap_config); + if (IS_ERR(regmap)) { + dev_err(dev, "failed to allocate register map\n"); + return PTR_ERR(regmap); + } + + ret = regmap_update_bits(regmap, TMP103_CONF_REG, TMP103_CONFIG_MASK, + TMP103_CONFIG); + if (ret < 0) { + dev_err(&client->dev, "error writing config register\n"); + return ret; + } + + i2c_set_clientdata(client, regmap); + hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + regmap, tmp103_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); +} + +#ifdef CONFIG_PM +static int tmp103_suspend(struct device *dev) +{ + struct regmap *regmap = dev_get_drvdata(dev); + + return regmap_update_bits(regmap, TMP103_CONF_REG, + TMP103_CONF_SD_MASK, 0); +} + +static int tmp103_resume(struct device *dev) +{ + struct regmap *regmap = dev_get_drvdata(dev); + + return regmap_update_bits(regmap, TMP103_CONF_REG, + TMP103_CONF_SD_MASK, TMP103_CONF_SD); +} + +static const struct dev_pm_ops tmp103_dev_pm_ops = { + .suspend = tmp103_suspend, + .resume = tmp103_resume, +}; + +#define TMP103_DEV_PM_OPS (&tmp103_dev_pm_ops) +#else +#define TMP103_DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + +static const struct i2c_device_id tmp103_id[] = { + { "tmp103", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, tmp103_id); + +static struct i2c_driver tmp103_driver = { + .driver = { + .name = "tmp103", + .pm = TMP103_DEV_PM_OPS, + }, + .probe = tmp103_probe, + .id_table = tmp103_id, +}; + +module_i2c_driver(tmp103_driver); + +MODULE_AUTHOR("Heiko Schocher <hs@denx.de>"); +MODULE_DESCRIPTION("Texas Instruments TMP103 temperature sensor driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/tmp421.c b/drivers/hwmon/tmp421.c index 7bab7a9bedc6..85d48d80822a 100644 --- a/drivers/hwmon/tmp421.c +++ b/drivers/hwmon/tmp421.c @@ -13,15 +13,11 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC. - * Supported models: TMP421, TMP422, TMP423 + * Supported models: TMP421, TMP422, TMP423, TMP441, TMP442 */ #include <linux/module.h> @@ -39,9 +35,10 @@ static const unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f, I2C_CLIENT_END }; -enum chips { tmp421, tmp422, tmp423 }; +enum chips { tmp421, tmp422, tmp423, tmp441, tmp442 }; /* The TMP421 registers */ +#define TMP421_STATUS_REG 0x08 #define TMP421_CONFIG_REG_1 0x09 #define TMP421_CONVERSION_RATE_REG 0x0B #define TMP421_MANUFACTURER_ID_REG 0xFE @@ -59,11 +56,15 @@ static const u8 TMP421_TEMP_LSB[4] = { 0x10, 0x11, 0x12, 0x13 }; #define TMP421_DEVICE_ID 0x21 #define TMP422_DEVICE_ID 0x22 #define TMP423_DEVICE_ID 0x23 +#define TMP441_DEVICE_ID 0x41 +#define TMP442_DEVICE_ID 0x42 static const struct i2c_device_id tmp421_id[] = { { "tmp421", 2 }, { "tmp422", 3 }, { "tmp423", 4 }, + { "tmp441", 2 }, + { "tmp442", 3 }, { } }; MODULE_DEVICE_TABLE(i2c, tmp421_id); @@ -234,7 +235,9 @@ static int tmp421_detect(struct i2c_client *client, { enum chips kind; struct i2c_adapter *adapter = client->adapter; - const char *names[] = { "TMP421", "TMP422", "TMP423" }; + const char * const names[] = { "TMP421", "TMP422", "TMP423", + "TMP441", "TMP442" }; + int addr = client->addr; u8 reg; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) @@ -244,17 +247,37 @@ static int tmp421_detect(struct i2c_client *client, if (reg != TMP421_MANUFACTURER_ID) return -ENODEV; + reg = i2c_smbus_read_byte_data(client, TMP421_CONVERSION_RATE_REG); + if (reg & 0xf8) + return -ENODEV; + + reg = i2c_smbus_read_byte_data(client, TMP421_STATUS_REG); + if (reg & 0x7f) + return -ENODEV; + reg = i2c_smbus_read_byte_data(client, TMP421_DEVICE_ID_REG); switch (reg) { case TMP421_DEVICE_ID: kind = tmp421; break; case TMP422_DEVICE_ID: + if (addr == 0x2a) + return -ENODEV; kind = tmp422; break; case TMP423_DEVICE_ID: + if (addr != 0x4c && addr != 0x4d) + return -ENODEV; kind = tmp423; break; + case TMP441_DEVICE_ID: + kind = tmp441; + break; + case TMP442_DEVICE_ID: + if (addr != 0x4c && addr != 0x4d) + return -ENODEV; + kind = tmp442; + break; default: return -ENODEV; } @@ -305,5 +328,5 @@ static struct i2c_driver tmp421_driver = { module_i2c_driver(tmp421_driver); MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>"); -MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor driver"); +MODULE_DESCRIPTION("Texas Instruments TMP421/422/423/441/442 temperature sensor driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/twl4030-madc-hwmon.c b/drivers/hwmon/twl4030-madc-hwmon.c index 6c6d440bb2dd..9a0e2b8e8b94 100644 --- a/drivers/hwmon/twl4030-madc-hwmon.c +++ b/drivers/hwmon/twl4030-madc-hwmon.c @@ -74,7 +74,7 @@ static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11); static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12); static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15); -static struct attribute *twl4030_madc_attributes[] = { +static struct attribute *twl4030_madc_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, @@ -91,46 +91,20 @@ static struct attribute *twl4030_madc_attributes[] = { &sensor_dev_attr_in15_input.dev_attr.attr, NULL }; - -static const struct attribute_group twl4030_madc_group = { - .attrs = twl4030_madc_attributes, -}; +ATTRIBUTE_GROUPS(twl4030_madc); static int twl4030_madc_hwmon_probe(struct platform_device *pdev) { - int ret; struct device *hwmon; - ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group); - if (ret) - goto err_sysfs; - hwmon = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon)) { - dev_err(&pdev->dev, "hwmon_device_register failed.\n"); - ret = PTR_ERR(hwmon); - goto err_reg; - } - - return 0; - -err_reg: - sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group); -err_sysfs: - - return ret; -} - -static int twl4030_madc_hwmon_remove(struct platform_device *pdev) -{ - hwmon_device_unregister(&pdev->dev); - sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group); - - return 0; + hwmon = devm_hwmon_device_register_with_groups(&pdev->dev, + "twl4030_madc", NULL, + twl4030_madc_groups); + return PTR_ERR_OR_ZERO(hwmon); } static struct platform_driver twl4030_madc_hwmon_driver = { .probe = twl4030_madc_hwmon_probe, - .remove = twl4030_madc_hwmon_remove, .driver = { .name = "twl4030_madc_hwmon", .owner = THIS_MODULE, diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index bdcf2dce5ec4..cb3765fec98c 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -249,19 +249,16 @@ static u8 fan_to_reg(long rpm, int div) * the bottom 7 bits will always be zero */ #define TEMP23_FROM_REG(val) ((val) / 128 * 500) -#define TEMP23_TO_REG(val) ((val) <= -128000 ? 0x8000 : \ - (val) >= 127500 ? 0x7F80 : \ - (val) < 0 ? ((val) - 250) / 500 * 128 : \ - ((val) + 250) / 500 * 128) +#define TEMP23_TO_REG(val) (DIV_ROUND_CLOSEST(clamp_val((val), -128000, \ + 127500), 500) * 128) /* for thermal cruise target temp, 7-bits, LSB = 1 degree Celsius */ -#define TARGET_TEMP_TO_REG(val) ((val) < 0 ? 0 : \ - (val) >= 127000 ? 127 : \ - ((val) + 500) / 1000) +#define TARGET_TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 127000), \ + 1000) /* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */ -#define TOL_TEMP_TO_REG(val) ((val) >= 15000 ? 15 : \ - ((val) + 500) / 1000) +#define TOL_TEMP_TO_REG(val) DIV_ROUND_CLOSEST(clamp_val((val), 0, 15000), \ + 1000) #define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) #define BEEP_MASK_FROM_REG(val) ((val) & 0xffffff) diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 32487c19cbfc..330299613d38 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -124,7 +124,7 @@ DIV_TO_REG(long val) } struct w83l786ng_data { - struct device *hwmon_dev; + struct i2c_client *client; struct mutex update_lock; char valid; /* !=0 if following fields are valid */ unsigned long last_updated; /* In jiffies */ @@ -148,32 +148,6 @@ struct w83l786ng_data { u8 tolerance[2]; }; -static int w83l786ng_probe(struct i2c_client *client, - const struct i2c_device_id *id); -static int w83l786ng_detect(struct i2c_client *client, - struct i2c_board_info *info); -static int w83l786ng_remove(struct i2c_client *client); -static void w83l786ng_init_client(struct i2c_client *client); -static struct w83l786ng_data *w83l786ng_update_device(struct device *dev); - -static const struct i2c_device_id w83l786ng_id[] = { - { "w83l786ng", 0 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, w83l786ng_id); - -static struct i2c_driver w83l786ng_driver = { - .class = I2C_CLASS_HWMON, - .driver = { - .name = "w83l786ng", - }, - .probe = w83l786ng_probe, - .remove = w83l786ng_remove, - .id_table = w83l786ng_id, - .detect = w83l786ng_detect, - .address_list = normal_i2c, -}; - static u8 w83l786ng_read_value(struct i2c_client *client, u8 reg) { @@ -186,6 +160,77 @@ w83l786ng_write_value(struct i2c_client *client, u8 reg, u8 value) return i2c_smbus_write_byte_data(client, reg, value); } +static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) +{ + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; + int i, j; + u8 reg_tmp, pwmcfg; + + mutex_lock(&data->update_lock); + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + dev_dbg(&client->dev, "Updating w83l786ng data.\n"); + + /* Update the voltages measured value and limits */ + for (i = 0; i < 3; i++) { + data->in[i] = w83l786ng_read_value(client, + W83L786NG_REG_IN(i)); + data->in_min[i] = w83l786ng_read_value(client, + W83L786NG_REG_IN_MIN(i)); + data->in_max[i] = w83l786ng_read_value(client, + W83L786NG_REG_IN_MAX(i)); + } + + /* Update the fan counts and limits */ + for (i = 0; i < 2; i++) { + data->fan[i] = w83l786ng_read_value(client, + W83L786NG_REG_FAN(i)); + data->fan_min[i] = w83l786ng_read_value(client, + W83L786NG_REG_FAN_MIN(i)); + } + + /* Update the fan divisor */ + reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV); + data->fan_div[0] = reg_tmp & 0x07; + data->fan_div[1] = (reg_tmp >> 4) & 0x07; + + pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); + for (i = 0; i < 2; i++) { + data->pwm_mode[i] = + ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1) + ? 0 : 1; + data->pwm_enable[i] = + ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1; + data->pwm[i] = + (w83l786ng_read_value(client, W83L786NG_REG_PWM[i]) + & 0x0f) * 0x11; + } + + + /* Update the temperature sensors */ + for (i = 0; i < 2; i++) { + for (j = 0; j < 3; j++) { + data->temp[i][j] = w83l786ng_read_value(client, + W83L786NG_REG_TEMP[i][j]); + } + } + + /* Update Smart Fan I/II tolerance */ + reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE); + data->tolerance[0] = reg_tmp & 0x0f; + data->tolerance[1] = (reg_tmp >> 4) & 0x0f; + + data->last_updated = jiffies; + data->valid = 1; + + } + + mutex_unlock(&data->update_lock); + + return data; +} + /* following are the sysfs callback functions */ #define show_in_reg(reg) \ static ssize_t \ @@ -207,8 +252,8 @@ store_in_##reg(struct device *dev, struct device_attribute *attr, \ const char *buf, size_t count) \ { \ int nr = to_sensor_dev_attr(attr)->index; \ - struct i2c_client *client = to_i2c_client(dev); \ - struct w83l786ng_data *data = i2c_get_clientdata(client); \ + struct w83l786ng_data *data = dev_get_drvdata(dev); \ + struct i2c_client *client = data->client; \ unsigned long val; \ int err = kstrtoul(buf, 10, &val); \ if (err) \ @@ -260,8 +305,8 @@ store_fan_min(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -298,8 +343,8 @@ store_fan_div(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long min; u8 tmp_fan_div; @@ -389,8 +434,8 @@ store_temp(struct device *dev, struct device_attribute *attr, to_sensor_dev_attr_2(attr); int nr = sensor_attr->nr; int index = sensor_attr->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; long val; int err; @@ -444,8 +489,8 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 reg; unsigned long val; int err; @@ -472,8 +517,8 @@ store_pwm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; unsigned long val; int err; @@ -496,8 +541,8 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 reg; unsigned long val; int err; @@ -552,8 +597,8 @@ store_tolerance(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { int nr = to_sensor_dev_attr(attr)->index; - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); + struct w83l786ng_data *data = dev_get_drvdata(dev); + struct i2c_client *client = data->client; u8 tol_tmp, tol_mask; unsigned long val; int err; @@ -608,7 +653,7 @@ static struct sensor_device_attribute sda_tolerance[] = { #define TOLERANCE_UNIT_ATTRS(X) \ &sda_tolerance[X].dev_attr.attr -static struct attribute *w83l786ng_attributes[] = { +static struct attribute *w83l786ng_attrs[] = { IN_UNIT_ATTRS(0), IN_UNIT_ATTRS(1), IN_UNIT_ATTRS(2), @@ -623,9 +668,7 @@ static struct attribute *w83l786ng_attributes[] = { NULL }; -static const struct attribute_group w83l786ng_group = { - .attrs = w83l786ng_attributes, -}; +ATTRIBUTE_GROUPS(w83l786ng); static int w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info) @@ -662,20 +705,33 @@ w83l786ng_detect(struct i2c_client *client, struct i2c_board_info *info) return 0; } +static void w83l786ng_init_client(struct i2c_client *client) +{ + u8 tmp; + + if (reset) + w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80); + + /* Start monitoring */ + tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG); + if (!(tmp & 0x01)) + w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01); +} + static int w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) { struct device *dev = &client->dev; struct w83l786ng_data *data; - int i, err = 0; + struct device *hwmon_dev; + int i; u8 reg_tmp; - data = devm_kzalloc(&client->dev, sizeof(struct w83l786ng_data), - GFP_KERNEL); + data = devm_kzalloc(dev, sizeof(struct w83l786ng_data), GFP_KERNEL); if (!data) return -ENOMEM; - i2c_set_clientdata(client, data); + data->client = client; mutex_init(&data->update_lock); /* Initialize the chip */ @@ -692,121 +748,28 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) data->fan_div[0] = reg_tmp & 0x07; data->fan_div[1] = (reg_tmp >> 4) & 0x07; - /* Register sysfs hooks */ - err = sysfs_create_group(&client->dev.kobj, &w83l786ng_group); - if (err) - goto exit_remove; - - data->hwmon_dev = hwmon_device_register(dev); - if (IS_ERR(data->hwmon_dev)) { - err = PTR_ERR(data->hwmon_dev); - goto exit_remove; - } - - return 0; - - /* Unregister sysfs hooks */ - -exit_remove: - sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); - return err; -} - -static int -w83l786ng_remove(struct i2c_client *client) -{ - struct w83l786ng_data *data = i2c_get_clientdata(client); - - hwmon_device_unregister(data->hwmon_dev); - sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); - - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, + data, + w83l786ng_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } -static void -w83l786ng_init_client(struct i2c_client *client) -{ - u8 tmp; - - if (reset) - w83l786ng_write_value(client, W83L786NG_REG_CONFIG, 0x80); - - /* Start monitoring */ - tmp = w83l786ng_read_value(client, W83L786NG_REG_CONFIG); - if (!(tmp & 0x01)) - w83l786ng_write_value(client, W83L786NG_REG_CONFIG, tmp | 0x01); -} - -static struct w83l786ng_data *w83l786ng_update_device(struct device *dev) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83l786ng_data *data = i2c_get_clientdata(client); - int i, j; - u8 reg_tmp, pwmcfg; - - mutex_lock(&data->update_lock); - if (time_after(jiffies, data->last_updated + HZ + HZ / 2) - || !data->valid) { - dev_dbg(&client->dev, "Updating w83l786ng data.\n"); - - /* Update the voltages measured value and limits */ - for (i = 0; i < 3; i++) { - data->in[i] = w83l786ng_read_value(client, - W83L786NG_REG_IN(i)); - data->in_min[i] = w83l786ng_read_value(client, - W83L786NG_REG_IN_MIN(i)); - data->in_max[i] = w83l786ng_read_value(client, - W83L786NG_REG_IN_MAX(i)); - } - - /* Update the fan counts and limits */ - for (i = 0; i < 2; i++) { - data->fan[i] = w83l786ng_read_value(client, - W83L786NG_REG_FAN(i)); - data->fan_min[i] = w83l786ng_read_value(client, - W83L786NG_REG_FAN_MIN(i)); - } - - /* Update the fan divisor */ - reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_FAN_DIV); - data->fan_div[0] = reg_tmp & 0x07; - data->fan_div[1] = (reg_tmp >> 4) & 0x07; - - pwmcfg = w83l786ng_read_value(client, W83L786NG_REG_FAN_CFG); - for (i = 0; i < 2; i++) { - data->pwm_mode[i] = - ((pwmcfg >> W83L786NG_PWM_MODE_SHIFT[i]) & 1) - ? 0 : 1; - data->pwm_enable[i] = - ((pwmcfg >> W83L786NG_PWM_ENABLE_SHIFT[i]) & 3) + 1; - data->pwm[i] = - (w83l786ng_read_value(client, W83L786NG_REG_PWM[i]) - & 0x0f) * 0x11; - } - - - /* Update the temperature sensors */ - for (i = 0; i < 2; i++) { - for (j = 0; j < 3; j++) { - data->temp[i][j] = w83l786ng_read_value(client, - W83L786NG_REG_TEMP[i][j]); - } - } - - /* Update Smart Fan I/II tolerance */ - reg_tmp = w83l786ng_read_value(client, W83L786NG_REG_TOLERANCE); - data->tolerance[0] = reg_tmp & 0x0f; - data->tolerance[1] = (reg_tmp >> 4) & 0x0f; - - data->last_updated = jiffies; - data->valid = 1; - - } - - mutex_unlock(&data->update_lock); +static const struct i2c_device_id w83l786ng_id[] = { + { "w83l786ng", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, w83l786ng_id); - return data; -} +static struct i2c_driver w83l786ng_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "w83l786ng", + }, + .probe = w83l786ng_probe, + .id_table = w83l786ng_id, + .detect = w83l786ng_detect, + .address_list = normal_i2c, +}; module_i2c_driver(w83l786ng_driver); diff --git a/drivers/hwmon/wm831x-hwmon.c b/drivers/hwmon/wm831x-hwmon.c index df6ceaf8d58a..3e6a3195cd11 100644 --- a/drivers/hwmon/wm831x-hwmon.c +++ b/drivers/hwmon/wm831x-hwmon.c @@ -29,17 +29,6 @@ #include <linux/mfd/wm831x/core.h> #include <linux/mfd/wm831x/auxadc.h> -struct wm831x_hwmon { - struct wm831x *wm831x; - struct device *classdev; -}; - -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "wm831x\n"); -} - static const char * const input_names[] = { [WM831X_AUX_SYSVDD] = "SYSVDD", [WM831X_AUX_USB] = "USB", @@ -50,15 +39,14 @@ static const char * const input_names[] = { [WM831X_AUX_BATT_TEMP] = "Battery", }; - static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, char *buf) { - struct wm831x_hwmon *hwmon = dev_get_drvdata(dev); + struct wm831x *wm831x = dev_get_drvdata(dev); int channel = to_sensor_dev_attr(attr)->index; int ret; - ret = wm831x_auxadc_read_uv(hwmon->wm831x, channel); + ret = wm831x_auxadc_read_uv(wm831x, channel); if (ret < 0) return ret; @@ -68,11 +56,11 @@ static ssize_t show_voltage(struct device *dev, static ssize_t show_chip_temp(struct device *dev, struct device_attribute *attr, char *buf) { - struct wm831x_hwmon *hwmon = dev_get_drvdata(dev); + struct wm831x *wm831x = dev_get_drvdata(dev); int channel = to_sensor_dev_attr(attr)->index; int ret; - ret = wm831x_auxadc_read(hwmon->wm831x, channel); + ret = wm831x_auxadc_read(wm831x, channel); if (ret < 0) return ret; @@ -100,8 +88,6 @@ static ssize_t show_label(struct device *dev, static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \ NULL, name) -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - WM831X_VOLTAGE(0, WM831X_AUX_AUX1); WM831X_VOLTAGE(1, WM831X_AUX_AUX2); WM831X_VOLTAGE(2, WM831X_AUX_AUX3); @@ -126,9 +112,7 @@ static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_voltage, NULL, static SENSOR_DEVICE_ATTR(temp2_label, S_IRUGO, show_label, NULL, WM831X_AUX_BATT_TEMP); -static struct attribute *wm831x_attributes[] = { - &dev_attr_name.attr, - +static struct attribute *wm831x_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, &sensor_dev_attr_in2_input.dev_attr.attr, @@ -153,55 +137,21 @@ static struct attribute *wm831x_attributes[] = { NULL }; -static const struct attribute_group wm831x_attr_group = { - .attrs = wm831x_attributes, -}; +ATTRIBUTE_GROUPS(wm831x); static int wm831x_hwmon_probe(struct platform_device *pdev) { struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent); - struct wm831x_hwmon *hwmon; - int ret; - - hwmon = devm_kzalloc(&pdev->dev, sizeof(struct wm831x_hwmon), - GFP_KERNEL); - if (!hwmon) - return -ENOMEM; - - hwmon->wm831x = wm831x; - - ret = sysfs_create_group(&pdev->dev.kobj, &wm831x_attr_group); - if (ret) - return ret; - - hwmon->classdev = hwmon_device_register(&pdev->dev); - if (IS_ERR(hwmon->classdev)) { - ret = PTR_ERR(hwmon->classdev); - goto err_sysfs; - } - - platform_set_drvdata(pdev, hwmon); - - return 0; - -err_sysfs: - sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group); - return ret; -} - -static int wm831x_hwmon_remove(struct platform_device *pdev) -{ - struct wm831x_hwmon *hwmon = platform_get_drvdata(pdev); - - hwmon_device_unregister(hwmon->classdev); - sysfs_remove_group(&pdev->dev.kobj, &wm831x_attr_group); + struct device *hwmon_dev; - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm831x", + wm831x, + wm831x_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static struct platform_driver wm831x_hwmon_driver = { .probe = wm831x_hwmon_probe, - .remove = wm831x_hwmon_remove, .driver = { .name = "wm831x-hwmon", .owner = THIS_MODULE, diff --git a/drivers/hwmon/wm8350-hwmon.c b/drivers/hwmon/wm8350-hwmon.c index 64bf75c9442b..90e3d918e597 100644 --- a/drivers/hwmon/wm8350-hwmon.c +++ b/drivers/hwmon/wm8350-hwmon.c @@ -28,19 +28,12 @@ #include <linux/mfd/wm8350/core.h> #include <linux/mfd/wm8350/comparator.h> -static ssize_t show_name(struct device *dev, - struct device_attribute *attr, char *buf) -{ - return sprintf(buf, "wm8350\n"); -} - static const char * const input_names[] = { [WM8350_AUXADC_USB] = "USB", [WM8350_AUXADC_LINE] = "Line", [WM8350_AUXADC_BATT] = "Battery", }; - static ssize_t show_voltage(struct device *dev, struct device_attribute *attr, char *buf) { @@ -68,15 +61,11 @@ static ssize_t show_label(struct device *dev, static SENSOR_DEVICE_ATTR(in##id##_label, S_IRUGO, show_label, \ NULL, name) -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); - WM8350_NAMED_VOLTAGE(0, WM8350_AUXADC_USB); WM8350_NAMED_VOLTAGE(1, WM8350_AUXADC_BATT); WM8350_NAMED_VOLTAGE(2, WM8350_AUXADC_LINE); -static struct attribute *wm8350_attributes[] = { - &dev_attr_name.attr, - +static struct attribute *wm8350_attrs[] = { &sensor_dev_attr_in0_input.dev_attr.attr, &sensor_dev_attr_in0_label.dev_attr.attr, &sensor_dev_attr_in1_input.dev_attr.attr, @@ -87,46 +76,21 @@ static struct attribute *wm8350_attributes[] = { NULL, }; -static const struct attribute_group wm8350_attr_group = { - .attrs = wm8350_attributes, -}; +ATTRIBUTE_GROUPS(wm8350); static int wm8350_hwmon_probe(struct platform_device *pdev) { struct wm8350 *wm8350 = platform_get_drvdata(pdev); - int ret; - - ret = sysfs_create_group(&pdev->dev.kobj, &wm8350_attr_group); - if (ret) - goto err; - - wm8350->hwmon.classdev = hwmon_device_register(&pdev->dev); - if (IS_ERR(wm8350->hwmon.classdev)) { - ret = PTR_ERR(wm8350->hwmon.classdev); - goto err_group; - } - - return 0; - -err_group: - sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group); -err: - return ret; -} - -static int wm8350_hwmon_remove(struct platform_device *pdev) -{ - struct wm8350 *wm8350 = platform_get_drvdata(pdev); - - hwmon_device_unregister(wm8350->hwmon.classdev); - sysfs_remove_group(&pdev->dev.kobj, &wm8350_attr_group); + struct device *hwmon_dev; - return 0; + hwmon_dev = devm_hwmon_device_register_with_groups(&pdev->dev, "wm8350", + wm8350, + wm8350_groups); + return PTR_ERR_OR_ZERO(hwmon_dev); } static struct platform_driver wm8350_hwmon_driver = { .probe = wm8350_hwmon_probe, - .remove = wm8350_hwmon_remove, .driver = { .name = "wm8350-hwmon", .owner = THIS_MODULE, diff --git a/include/linux/platform_data/ntc_thermistor.h b/include/linux/platform_data/ntc_thermistor.h index c7285b575462..0a6de4ca4930 100644 --- a/include/linux/platform_data/ntc_thermistor.h +++ b/include/linux/platform_data/ntc_thermistor.h @@ -26,6 +26,7 @@ struct iio_channel; enum ntc_thermistor_type { TYPE_NCPXXWB473, TYPE_NCPXXWL333, + TYPE_B57330V2103, }; struct ntc_thermistor_platform_data { |