diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 13:50:06 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 13:50:06 -0700 |
commit | cc150a2861e744d8f574d571762cc7e9f928abb3 (patch) | |
tree | a1567d76fc52dc56ba483d7dafa82fada5fc28ba | |
parent | d9a807461fc8cc0d6ba589ea0730d139122af012 (diff) | |
parent | 592758b12f2e327bb5902dabd3d36b2e86049871 (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:
"New drivers for: MCP3221, ADT7410, MAX197
Chip support added to existing drivers: LM71, LM74, MAX1110, MAX1112,
MAX1113, INA220, INA230, MCP3221
Cleanup: Use devm_ functions, fixed build warnings, removed deprecated
sysfs attributes, code simplifications, dropped dependencies on
EXPERIMENTAL"
* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (64 commits)
hwmon: (mcp3021) Add MCP3221 support
hwmon: (mcp3021) Prepare MCP3021 driver to support other chips
hwmon: (w83791d) Drop unnecessary compare statements
hwmon: (lm93) Drop unnecessary compare statement
hwmon: (lm70) Simplify show_name function
hwmon: (adcxx) Simplify show_name function
hwmon: Drop dependencies on EXPERIMENTAL
hwmon: (it87) Fix Kconfig for IT87 driver
hwmon: (sht15) move header to linux/platform_data/
hwmon: (asus_atk0110) Remove useless kfree
hwmon: (ina2xx) Add support for INA220 and INA230
hwmon: (ina2xx) Use structure array to distinguish chip types
hwmon: (max1111) Add support for MAX1110, MAX1112, and MAX1113
hwmon: (lm70) Add support for LM71 and LM74
hwmon: (Documentation) Update feature-removal-schedule.txt
hwmon: (w83793) Remove legacy chassis intrusion detection sysfs attributes
hwmon: (w83792d) Remove legacy chassis intrusion detection attributes
hwmon: (adm9240) Remove legacy chassis intrusion detection sysfs attribute
hwmon: (lm70) Allow 4wire SPI bus with LM70
hwmon: (sht15) remove multiple driver registration
...
61 files changed, 1528 insertions, 882 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 43975ba1fde..72bab3fe428 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -357,16 +357,6 @@ Who: Wey-Yi Guy <wey-yi.w.guy@intel.com> ---------------------------- -What: Legacy, non-standard chassis intrusion detection interface. -When: June 2011 -Why: The adm9240, w83792d and w83793 hardware monitoring drivers have - legacy interfaces for chassis intrusion detection. A standard - interface has been added to each driver, so the legacy interface - can be removed. -Who: Jean Delvare <khali@linux-fr.org> - ----------------------------- - What: i2c_driver.attach_adapter i2c_driver.detach_adapter When: September 2011 diff --git a/Documentation/hwmon/adt7410 b/Documentation/hwmon/adt7410 new file mode 100644 index 00000000000..96004000dc2 --- /dev/null +++ b/Documentation/hwmon/adt7410 @@ -0,0 +1,51 @@ +Kernel driver adt7410 +===================== + +Supported chips: + * Analog Devices ADT7410 + Prefix: 'adt7410' + Addresses scanned: I2C 0x48 - 0x4B + Datasheet: Publicly available at the Analog Devices website + http://www.analog.com/static/imported-files/data_sheets/ADT7410.pdf + +Author: Hartmut Knaack <knaack.h@gmx.de> + +Description +----------- + +The ADT7410 is a temperature sensor with rated temperature range of -55°C to ++150°C. It has a high accuracy of +/-0.5°C and can be operated at a resolution +of 13 bits (0.0625°C) or 16 bits (0.0078°C). The sensor provides an INT pin to +indicate that a minimum or maximum temperature set point has been exceeded, as +well as a critical temperature (CT) pin to indicate that the critical +temperature set point has been exceeded. Both pins can be set up with a common +hysteresis of 0°C - 15°C and a fault queue, ranging from 1 to 4 events. Both +pins can individually set to be active-low or active-high, while the whole +device can either run in comparator mode or interrupt mode. The ADT7410 +supports continous temperature sampling, as well as sampling one temperature +value per second or even justget one sample on demand for power saving. +Besides, it can completely power down its ADC, if power management is +required. + +Configuration Notes +------------------- + +Since the device uses one hysteresis value, which is an offset to minimum, +maximum and critical temperature, it can only be set for temp#_max_hyst. +However, temp#_min_hyst and temp#_crit_hyst show their corresponding +hysteresis. +The device is set to 16 bit resolution and comparator mode. + +sysfs-Interface +--------------- + +temp#_input - temperature input +temp#_min - temperature minimum setpoint +temp#_max - temperature maximum setpoint +temp#_crit - critical temperature setpoint +temp#_min_hyst - hysteresis for temperature minimum (read-only) +temp#_max_hyst - hysteresis for temperature maximum (read/write) +temp#_crit_hyst - hysteresis for critical temperature (read-only) +temp#_min_alarm - temperature minimum alarm flag +temp#_max_alarm - temperature maximum alarm flag +temp#_crit_alarm - critical temperature alarm flag diff --git a/Documentation/hwmon/ina2xx b/Documentation/hwmon/ina2xx index f50a6cc2761..03444f9d833 100644 --- a/Documentation/hwmon/ina2xx +++ b/Documentation/hwmon/ina2xx @@ -8,12 +8,24 @@ Supported chips: Datasheet: Publicly available at the Texas Instruments website http://www.ti.com/ + * Texas Instruments INA220 + Prefix: 'ina220' + Addresses: I2C 0x40 - 0x4f + Datasheet: Publicly available at the Texas Instruments website + http://www.ti.com/ + * Texas Instruments INA226 Prefix: 'ina226' Addresses: I2C 0x40 - 0x4f Datasheet: Publicly available at the Texas Instruments website http://www.ti.com/ + * Texas Instruments INA230 + Prefix: 'ina230' + Addresses: I2C 0x40 - 0x4f + Datasheet: Publicly available at the Texas Instruments website + http://www.ti.com/ + Author: Lothar Felten <l-felten@ti.com> Description @@ -23,7 +35,13 @@ The INA219 is a high-side current shunt and power monitor with an I2C interface. The INA219 monitors both shunt drop and supply voltage, with programmable conversion times and filtering. +The INA220 is a high or low side current shunt and power monitor with an I2C +interface. The INA220 monitors both shunt drop and supply voltage. + The INA226 is a current shunt and power monitor with an I2C interface. The INA226 monitors both a shunt voltage drop and bus supply voltage. +The INA230 is a high or low side current shunt and power monitor with an I2C +interface. The INA230 monitors both a shunt voltage drop and bus supply voltage. + The shunt value in micro-ohms can be set via platform data. diff --git a/Documentation/hwmon/lm70 b/Documentation/hwmon/lm70 index 0d240291e3c..86d182942c5 100644 --- a/Documentation/hwmon/lm70 +++ b/Documentation/hwmon/lm70 @@ -6,6 +6,10 @@ Supported chips: Datasheet: http://www.national.com/pf/LM/LM70.html * Texas Instruments TMP121/TMP123 Information: http://focus.ti.com/docs/prod/folders/print/tmp121.html + * National Semiconductor LM71 + Datasheet: http://www.ti.com/product/LM71 + * National Semiconductor LM74 + Datasheet: http://www.ti.com/product/LM74 Author: Kaiwan N Billimoria <kaiwan@designergraphix.com> @@ -31,9 +35,11 @@ As a real (in-tree) example of this "SPI protocol driver" interfacing with a "SPI master controller driver", see drivers/spi/spi_lm70llp.c and its associated documentation. -The TMP121/TMP123 are very similar; main differences are 4 wire SPI inter- -face (read only) and 13-bit temperature data (0.0625 degrees celsius reso- -lution). +The LM74 and TMP121/TMP123 are very similar; main difference is 13-bit +temperature data (0.0625 degrees celsius resolution). + +The LM71 is also very similar; main difference is 14-bit temperature +data (0.03125 degrees celsius resolution). Thanks to --------- diff --git a/Documentation/hwmon/max197 b/Documentation/hwmon/max197 new file mode 100644 index 00000000000..8d89b9009df --- /dev/null +++ b/Documentation/hwmon/max197 @@ -0,0 +1,60 @@ +Maxim MAX197 driver +=================== + +Author: + * Vivien Didelot <vivien.didelot@savoirfairelinux.com> + +Supported chips: + * Maxim MAX197 + Prefix: 'max197' + Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX197.pdf + + * Maxim MAX199 + Prefix: 'max199' + Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX199.pdf + +Description +----------- + +The A/D converters MAX197, and MAX199 are both 8-Channel, Multi-Range, 5V, +12-Bit DAS with 8+4 Bus Interface and Fault Protection. + +The available ranges for the MAX197 are {0,-5V} to 5V, and {0,-10V} to 10V, +while they are {0,-2V} to 2V, and {0,-4V} to 4V on the MAX199. + +Platform data +------------- + +The MAX197 platform data (defined in linux/platform_data/max197.h) should be +filled with a pointer to a conversion function, defined like: + + int convert(u8 ctrl); + +ctrl is the control byte to write to start a new conversion. +On success, the function must return the 12-bit raw value read from the chip, +or a negative error code otherwise. + +Control byte format: + +Bit Name Description +7,6 PD1,PD0 Clock and Power-Down modes +5 ACQMOD Internal or External Controlled Acquisition +4 RNG Full-scale voltage magnitude at the input +3 BIP Unipolar or Bipolar conversion mode +2,1,0 A2,A1,A0 Channel + +Sysfs interface +--------------- + +* in[0-7]_input: The conversion value for the corresponding channel. + RO + +* in[0-7]_min: The lower limit (in mV) for the corresponding channel. + For the MAX197, it will be adjusted to -10000, -5000, or 0. + For the MAX199, it will be adjusted to -4000, -2000, or 0. + RW + +* in[0-7]_max: The higher limit (in mV) for the corresponding channel. + For the MAX197, it will be adjusted to 0, 5000, or 10000. + For the MAX199, it will be adjusted to 0, 2000, or 4000. + RW diff --git a/Documentation/hwmon/mcp3021 b/Documentation/hwmon/mcp3021 index 325fd87e81b..74a6b72adf5 100644 --- a/Documentation/hwmon/mcp3021 +++ b/Documentation/hwmon/mcp3021 @@ -5,18 +5,25 @@ Supported chips: * Microchip Technology MCP3021 Prefix: 'mcp3021' Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21805a.pdf + * Microchip Technology MCP3221 + Prefix: 'mcp3221' + Datasheet: http://ww1.microchip.com/downloads/en/DeviceDoc/21732c.pdf -Author: Mingkai Hu +Authors: + Mingkai Hu + Sven Schuchmann <schuchmann@schleissheimer.de> Description ----------- -This driver implements support for the Microchip Technology MCP3021 chip. +This driver implements support for the Microchip Technology MCP3021 and +MCP3221 chip. The Microchip Technology Inc. MCP3021 is a successive approximation A/D -converter (ADC) with 10-bit resolution. -This device provides one single-ended input with very low power consumption. -Communication to the MCP3021 is performed using a 2-wire I2C compatible -interface. Standard (100 kHz) and Fast (400 kHz) I2C modes are available. -The default I2C device address is 0x4d (contact the Microchip factory for -additional address options). +converter (ADC) with 10-bit resolution. The MCP3221 has 12-bit resolution. + +These devices provide one single-ended input with very low power consumption. +Communication to the MCP3021/MCP3221 is performed using a 2-wire I2C +compatible interface. Standard (100 kHz) and Fast (400 kHz) I2C modes are +available. The default I2C device address is 0x4d (contact the Microchip +factory for additional address options). diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c index 30b1b0b3c7f..0701ca79e7d 100644 --- a/arch/arm/mach-pxa/stargate2.c +++ b/arch/arm/mach-pxa/stargate2.c @@ -52,7 +52,7 @@ #include <linux/spi/spi.h> #include <linux/spi/pxa2xx_spi.h> #include <linux/mfd/da903x.h> -#include <linux/sht15.h> +#include <linux/platform_data/sht15.h> #include "devices.h" #include "generic.h" diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index b0a2e4c37e1..c74e73b2069 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig @@ -41,7 +41,7 @@ comment "Native drivers" config SENSORS_ABITUGURU tristate "Abit uGuru (rev 1 & 2)" - depends on X86 && DMI && EXPERIMENTAL + depends on X86 && DMI help If you say yes here you get support for the sensor part of the first and second revision of the Abit uGuru chip. The voltage and frequency @@ -56,7 +56,7 @@ config SENSORS_ABITUGURU config SENSORS_ABITUGURU3 tristate "Abit uGuru (rev 3)" - depends on X86 && DMI && EXPERIMENTAL + depends on X86 && DMI help If you say yes here you get support for the sensor part of the third revision of the Abit uGuru chip. Only reading the sensors @@ -70,7 +70,7 @@ config SENSORS_ABITUGURU3 config SENSORS_AD7314 tristate "Analog Devices AD7314 and compatibles" - depends on SPI && EXPERIMENTAL + depends on SPI help If you say yes here you get support for the Analog Devices AD7314, ADT7301 and ADT7302 temperature sensors. @@ -80,7 +80,7 @@ config SENSORS_AD7314 config SENSORS_AD7414 tristate "Analog Devices AD7414" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Analog Devices AD7414 temperature monitoring chip. @@ -90,7 +90,7 @@ config SENSORS_AD7414 config SENSORS_AD7418 tristate "Analog Devices AD7416, AD7417 and AD7418" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Analog Devices AD7416, AD7417 and AD7418 temperature monitoring chips. @@ -100,7 +100,7 @@ config SENSORS_AD7418 config SENSORS_ADCXX tristate "National Semiconductor ADCxxxSxxx" - depends on SPI_MASTER && EXPERIMENTAL + depends on SPI_MASTER help If you say yes here you get support for the National Semiconductor ADC<bb><c>S<sss> chip family, where @@ -179,9 +179,19 @@ config SENSORS_ADM9240 This driver can also be built as a module. If so, the module will be called adm9240. +config SENSORS_ADT7410 + tristate "Analog Devices ADT7410" + depends on I2C + help + If you say yes here you get support for the Analog Devices + ADT7410 temperature monitoring chip. + + This driver can also be built as a module. If so, the module + will be called adt7410. + config SENSORS_ADT7411 tristate "Analog Devices ADT7411" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Analog Devices ADT7411 voltage and temperature monitoring chip. @@ -191,7 +201,7 @@ config SENSORS_ADT7411 config SENSORS_ADT7462 tristate "Analog Devices ADT7462" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Analog Devices ADT7462 temperature monitoring chips. @@ -201,7 +211,7 @@ config SENSORS_ADT7462 config SENSORS_ADT7470 tristate "Analog Devices ADT7470" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Analog Devices ADT7470 temperature monitoring chips. @@ -236,7 +246,7 @@ config SENSORS_ASC7621 config SENSORS_K8TEMP tristate "AMD Athlon64/FX or Opteron temperature sensor" - depends on X86 && PCI && EXPERIMENTAL + depends on X86 && PCI help If you say yes here you get support for the temperature sensor(s) inside your CPU. Supported is whole AMD K8 @@ -271,7 +281,7 @@ config SENSORS_FAM15H_POWER config SENSORS_ASB100 tristate "Asus ASB100 Bach" - depends on X86 && I2C && EXPERIMENTAL + depends on X86 && I2C select HWMON_VID help If you say yes here you get support for the ASB100 Bach sensor @@ -282,7 +292,7 @@ config SENSORS_ASB100 config SENSORS_ATXP1 tristate "Attansic ATXP1 VID controller" - depends on I2C && EXPERIMENTAL + depends on I2C select HWMON_VID help If you say yes here you get support for the Attansic ATXP1 VID @@ -336,7 +346,7 @@ config SENSORS_EXYNOS4_TMU config SENSORS_I5K_AMB tristate "FB-DIMM AMB temperature sensor on Intel 5000 series chipsets" - depends on PCI && EXPERIMENTAL + depends on PCI help If you say yes here you get support for FB-DIMM AMB temperature monitoring chips on systems with the Intel 5000 series chipset. @@ -445,7 +455,7 @@ config SENSORS_GPIO_FAN config SENSORS_HIH6130 tristate "Honeywell Humidicon HIH-6130 humidity/temperature sensor" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for Honeywell Humidicon HIH-6130 and HIH-6131 Humidicon humidity sensors. @@ -455,7 +465,7 @@ config SENSORS_HIH6130 config SENSORS_CORETEMP tristate "Intel Core/Core2/Atom temperature sensor" - depends on X86 && PCI && EXPERIMENTAL + depends on X86 && PCI help If you say yes here you get support for the temperature sensor inside your CPU. Most of the family 6 CPUs @@ -495,8 +505,8 @@ config SENSORS_IT87 select HWMON_VID help If you say yes here you get support for ITE IT8705F, IT8712F, - IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F and IT8758E - sensor chips, and the SiS960 clone. + IT8716F, IT8718F, IT8720F, IT8721F, IT8726F, IT8728F, IT8758E, + IT8782F, and IT8783E/F sensor chips, and the SiS950 clone. This driver can also be built as a module. If so, the module will be called it87. @@ -527,7 +537,7 @@ config SENSORS_JC42 config SENSORS_LINEAGE tristate "Lineage Compact Power Line Power Entry Module" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Lineage Compact Power Line series of DC/DC and AC/DC converters such as CP1800, CP2000AC, @@ -550,12 +560,12 @@ config SENSORS_LM63 will be called lm63. config SENSORS_LM70 - tristate "National Semiconductor LM70 / Texas Instruments TMP121" + tristate "National Semiconductor LM70 and compatibles" depends on SPI_MASTER help If you say yes here you get support for the National Semiconductor - LM70 and Texas Instruments TMP121/TMP123 digital temperature - sensor chips. + LM70, LM71, LM74 and Texas Instruments TMP121/TMP123 digital tempera- + ture sensor chips. This driver can also be built as a module. If so, the module will be called lm70. @@ -709,7 +719,7 @@ config SENSORS_LTC4151 config SENSORS_LTC4215 tristate "Linear Technology LTC4215" - depends on I2C && EXPERIMENTAL + depends on I2C default n help If you say yes here you get support for Linear Technology LTC4215 @@ -720,7 +730,7 @@ config SENSORS_LTC4215 config SENSORS_LTC4245 tristate "Linear Technology LTC4245" - depends on I2C && EXPERIMENTAL + depends on I2C default n help If you say yes here you get support for Linear Technology LTC4245 @@ -731,7 +741,7 @@ config SENSORS_LTC4245 config SENSORS_LTC4261 tristate "Linear Technology LTC4261" - depends on I2C && EXPERIMENTAL + depends on I2C default n help If you say yes here you get support for Linear Technology LTC4261 @@ -752,7 +762,7 @@ config SENSORS_LM95241 config SENSORS_LM95245 tristate "National Semiconductor LM95245 sensor chip" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for LM95245 sensor chip. @@ -760,10 +770,11 @@ config SENSORS_LM95245 will be called lm95245. config SENSORS_MAX1111 - tristate "Maxim MAX1111 Multichannel, Serial 8-bit ADC chip" + tristate "Maxim MAX1111 Serial 8-bit ADC chip and compatibles" depends on SPI_MASTER help - Say y here to support Maxim's MAX1111 ADC chips. + Say y here to support Maxim's MAX1110, MAX1111, MAX1112, and MAX1113 + ADC chips. This driver can also be built as a module. If so, the module will be called max1111. @@ -795,7 +806,7 @@ config SENSORS_MAX1619 config SENSORS_MAX1668 tristate "Maxim MAX1668 and compatibles" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for MAX1668, MAX1989 and MAX1805 chips. @@ -803,9 +814,18 @@ config SENSORS_MAX1668 This driver can also be built as a module. If so, the module will be called max1668. +config SENSORS_MAX197 + tristate "Maxim MAX197 and compatibles" + help + Support for the Maxim MAX197 A/D converter. + Support will include, but not be limited to, MAX197, and MAX199. + + This driver can also be built as a module. If so, the module + will be called max197. + config SENSORS_MAX6639 tristate "Maxim MAX6639 sensor chip" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the MAX6639 sensor chips. @@ -815,7 +835,7 @@ config SENSORS_MAX6639 config SENSORS_MAX6642 tristate "Maxim MAX6642 sensor chip" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for MAX6642 sensor chip. MAX6642 is a SMBus-Compatible Remote/Local Temperature Sensor @@ -826,7 +846,7 @@ config SENSORS_MAX6642 config SENSORS_MAX6650 tristate "Maxim MAX6650 sensor chip" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the MAX6650 / MAX6651 sensor chips. @@ -835,18 +855,18 @@ config SENSORS_MAX6650 will be called max6650. config SENSORS_MCP3021 - tristate "Microchip MCP3021" - depends on I2C && EXPERIMENTAL + tristate "Microchip MCP3021 and compatibles" + depends on I2C help - If you say yes here you get support for the MCP3021 chip - that is a A/D converter (ADC) with 10-bit resolution. + If you say yes here you get support for MCP3021 and MCP3221. + The MCP3021 is a A/D converter (ADC) with 10-bit and the MCP3221 + with 12-bit resolution. This driver can also be built as a module. If so, the module will be called mcp3021. config SENSORS_NTC_THERMISTOR tristate "NTC thermistor support" - depends on EXPERIMENTAL help This driver supports NTC thermistors sensor reading and its interpretation. The driver can also monitor the temperature and @@ -951,7 +971,7 @@ config SENSORS_SIS5595 config SENSORS_SMM665 tristate "Summit Microelectronics SMM665" - depends on I2C && EXPERIMENTAL + depends on I2C default n help If you say yes here you get support for the hardware monitoring @@ -966,7 +986,7 @@ config SENSORS_SMM665 config SENSORS_DME1737 tristate "SMSC DME1737, SCH311x and compatibles" - depends on I2C && EXPERIMENTAL && !PPC + depends on I2C && !PPC select HWMON_VID help If you say yes here you get support for the hardware monitoring @@ -1042,7 +1062,7 @@ config SENSORS_SMSC47M192 config SENSORS_SMSC47B397 tristate "SMSC LPC47B397-NC" - depends on EXPERIMENTAL && !PPC + depends on !PPC help If you say yes here you get support for the SMSC LPC47B397-NC sensor chip. @@ -1116,7 +1136,7 @@ config SENSORS_ADS7871 config SENSORS_AMC6821 tristate "Texas Instruments AMC6821" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Texas Instruments AMC6821 hardware monitoring chips. @@ -1125,11 +1145,11 @@ config SENSORS_AMC6821 will be called amc6821. config SENSORS_INA2XX - tristate "Texas Instruments INA219, INA226" - depends on I2C && EXPERIMENTAL + tristate "Texas Instruments INA219 and compatibles" + depends on I2C help - If you say yes here you get support for INA219 and INA226 power - monitor chips. + If you say yes here you get support for INA219, INA220, INA226, and + INA230 power monitor chips. The INA2xx driver is configured for the default configuration of the part as described in the datasheet. @@ -1149,7 +1169,7 @@ config SENSORS_THMC50 config SENSORS_TMP102 tristate "Texas Instruments TMP102" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for Texas Instruments TMP102 sensor chips. @@ -1159,7 +1179,7 @@ config SENSORS_TMP102 config SENSORS_TMP401 tristate "Texas Instruments TMP401 and compatibles" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for Texas Instruments TMP401 and TMP411 temperature sensor chips. @@ -1169,7 +1189,7 @@ config SENSORS_TMP401 config SENSORS_TMP421 tristate "Texas Instruments TMP421 and compatible" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for Texas Instruments TMP421, TMP422 and TMP423 temperature sensor chips. @@ -1261,7 +1281,7 @@ config SENSORS_W83792D config SENSORS_W83793 tristate "Winbond W83793" - depends on I2C && EXPERIMENTAL + depends on I2C select HWMON_VID help If you say yes here you get support for the Winbond W83793 @@ -1273,7 +1293,7 @@ config SENSORS_W83793 config SENSORS_W83795 tristate "Winbond/Nuvoton W83795G/ADG" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Winbond W83795G and W83795ADG hardware monitoring chip, including manual fan speed @@ -1284,7 +1304,7 @@ config SENSORS_W83795 config SENSORS_W83795_FANCTRL boolean "Include automatic fan control support (DANGEROUS)" - depends on SENSORS_W83795 && EXPERIMENTAL + depends on SENSORS_W83795 default n help If you say yes here, support for automatic fan speed control @@ -1301,7 +1321,7 @@ config SENSORS_W83795_FANCTRL config SENSORS_W83L785TS tristate "Winbond W83L785TS-S" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Winbond W83L785TS-S sensor chip, which is used on the Asus A7N8X, among other @@ -1312,7 +1332,7 @@ config SENSORS_W83L785TS config SENSORS_W83L786NG tristate "Winbond W83L786NG, W83L786NR" - depends on I2C && EXPERIMENTAL + depends on I2C help If you say yes here you get support for the Winbond W83L786NG and W83L786NR sensor chips. @@ -1427,7 +1447,7 @@ config SENSORS_ACPI_POWER config SENSORS_ATK0110 tristate "ASUS ATK0110" - depends on X86 && EXPERIMENTAL + depends on X86 help If you say yes here you get support for the ACPI hardware monitoring interface found in many ASUS motherboards. This diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 7aa98119c4a..a62ce17ddbf 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile @@ -34,6 +34,7 @@ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o obj-$(CONFIG_SENSORS_ADS1015) += ads1015.o obj-$(CONFIG_SENSORS_ADS7828) += ads7828.o obj-$(CONFIG_SENSORS_ADS7871) += ads7871.o +obj-$(CONFIG_SENSORS_ADT7410) += adt7410.o obj-$(CONFIG_SENSORS_ADT7411) += adt7411.o obj-$(CONFIG_SENSORS_ADT7462) += adt7462.o obj-$(CONFIG_SENSORS_ADT7470) += adt7470.o @@ -94,6 +95,7 @@ obj-$(CONFIG_SENSORS_MAX1111) += max1111.o obj-$(CONFIG_SENSORS_MAX16065) += max16065.o obj-$(CONFIG_SENSORS_MAX1619) += max1619.o obj-$(CONFIG_SENSORS_MAX1668) += max1668.o +obj-$(CONFIG_SENSORS_MAX197) += max197.o obj-$(CONFIG_SENSORS_MAX6639) += max6639.o obj-$(CONFIG_SENSORS_MAX6642) += max6642.o obj-$(CONFIG_SENSORS_MAX6650) += max6650.o diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c index d4419b47f3d..78b81793ddd 100644 --- a/drivers/hwmon/abituguru.c +++ b/drivers/hwmon/abituguru.c @@ -1278,7 +1278,8 @@ static int __devinit abituguru_probe(struct platform_device *pdev) 0x00, 0x01, 0x03, 0x04, 0x0A, 0x08, 0x0E, 0x02, 0x09, 0x06, 0x05, 0x0B, 0x0F, 0x0D, 0x07, 0x0C }; - data = kzalloc(sizeof(struct abituguru_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -1430,8 +1431,6 @@ abituguru_probe_error: for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru_sysfs_attr[i].dev_attr); - platform_set_drvdata(pdev, NULL); - kfree(data); return res; } @@ -1446,8 +1445,6 @@ static int __devexit abituguru_remove(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru_sysfs_attr[i].dev_attr); - platform_set_drvdata(pdev, NULL); - kfree(data); return 0; } diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c index 5d582aebff8..b174b8b2b4d 100644 --- a/drivers/hwmon/abituguru3.c +++ b/drivers/hwmon/abituguru3.c @@ -976,7 +976,8 @@ static int __devinit abituguru3_probe(struct platform_device *pdev) u8 buf[2]; u16 id; - data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct abituguru3_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -1068,7 +1069,6 @@ abituguru3_probe_error: for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru3_sysfs_attr[i].dev_attr); - kfree(data); return res; } @@ -1084,8 +1084,6 @@ static int __devexit abituguru3_remove(struct platform_device *pdev) for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++) device_remove_file(&pdev->dev, &abituguru3_sysfs_attr[i].dev_attr); - kfree(data); - return 0; } diff --git a/drivers/hwmon/ad7314.c b/drivers/hwmon/ad7314.c index f915eb1c29f..37c01e72d69 100644 --- a/drivers/hwmon/ad7314.c +++ b/drivers/hwmon/ad7314.c @@ -112,16 +112,16 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev) int ret; struct ad7314_data *chip; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) { - ret = -ENOMEM; - goto error_ret; - } + chip = devm_kzalloc(&spi_dev->dev, sizeof(*chip), GFP_KERNEL); + if (chip == NULL) + return -ENOMEM; + dev_set_drvdata(&spi_dev->dev, chip); ret = sysfs_create_group(&spi_dev->dev.kobj, &ad7314_group); if (ret < 0) - goto error_free_chip; + return ret; + chip->hwmon_dev = hwmon_device_register(&spi_dev->dev); if (IS_ERR(chip->hwmon_dev)) { ret = PTR_ERR(chip->hwmon_dev); @@ -132,9 +132,6 @@ static int __devinit ad7314_probe(struct spi_device *spi_dev) return 0; error_remove_group: sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); -error_free_chip: - kfree(chip); -error_ret: return ret; } @@ -144,7 +141,6 @@ static int __devexit ad7314_remove(struct spi_device *spi_dev) hwmon_device_unregister(chip->hwmon_dev); sysfs_remove_group(&spi_dev->dev.kobj, &ad7314_group); - kfree(chip); return 0; } diff --git a/drivers/hwmon/ad7414.c b/drivers/hwmon/ad7414.c index 06d2d60d1fd..b420fb3f3a7 100644 --- a/drivers/hwmon/ad7414.c +++ b/drivers/hwmon/ad7414.c @@ -185,16 +185,13 @@ static int ad7414_probe(struct i2c_client *client, int err; if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA)) { - err = -EOPNOTSUPP; - goto exit; - } + I2C_FUNC_SMBUS_READ_WORD_DATA)) + return -EOPNOTSUPP; - data = kzalloc(sizeof(struct ad7414_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct ad7414_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->lock); @@ -214,7 +211,7 @@ static int ad7414_probe(struct i2c_client *client, /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &ad7414_group); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -226,9 +223,6 @@ static int ad7414_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &ad7414_group); -exit_free: - kfree(data); -exit: return err; } @@ -238,7 +232,6 @@ static int __devexit ad7414_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &ad7414_group); - kfree(data); return 0; } diff --git a/drivers/hwmon/ad7418.c b/drivers/hwmon/ad7418.c index a50a6bef16c..57d4a629567 100644 --- a/drivers/hwmon/ad7418.c +++ b/drivers/hwmon/ad7418.c @@ -227,16 +227,13 @@ static int ad7418_probe(struct i2c_client *client, int err; if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA | - I2C_FUNC_SMBUS_WORD_DATA)) { - err = -EOPNOTSUPP; - goto exit; - } + I2C_FUNC_SMBUS_WORD_DATA)) + return -EOPNOTSUPP; - data = kzalloc(sizeof(struct ad7418_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct ad7418_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); @@ -268,7 +265,7 @@ static int ad7418_probe(struct i2c_client *client, /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &data->attrs); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -280,9 +277,6 @@ static int ad7418_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &data->attrs); -exit_free: - kfree(data); -exit: return err; } @@ -291,7 +285,6 @@ static int ad7418_remove(struct i2c_client *client) struct ad7418_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); - kfree(data); return 0; } diff --git a/drivers/hwmon/adcxx.c b/drivers/hwmon/adcxx.c index a3d3183454a..f4c5867170d 100644 --- a/drivers/hwmon/adcxx.c +++ b/drivers/hwmon/adcxx.c @@ -141,10 +141,7 @@ static ssize_t adcxx_set_max(struct device *dev, static ssize_t adcxx_show_name(struct device *dev, struct device_attribute *devattr, char *buf) { - struct spi_device *spi = to_spi_device(dev); - struct adcxx *adc = spi_get_drvdata(spi); - - return sprintf(buf, "adcxx%ds\n", adc->channels); + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); } static struct sensor_device_attribute ad_input[] = { @@ -171,7 +168,7 @@ static int __devinit adcxx_probe(struct spi_device *spi) int status; int i; - adc = kzalloc(sizeof *adc, GFP_KERNEL); + adc = devm_kzalloc(&spi->dev, sizeof(*adc), GFP_KERNEL); if (!adc) return -ENOMEM; @@ -208,7 +205,6 @@ out_err: spi_set_drvdata(spi, NULL); mutex_unlock(&adc->lock); - kfree(adc); return status; } @@ -224,7 +220,6 @@ static int __devexit adcxx_remove(struct spi_device *spi) spi_set_drvdata(spi, NULL); mutex_unlock(&adc->lock); - kfree(adc); return 0; } diff --git a/drivers/hwmon/adm1029.c b/drivers/hwmon/adm1029.c index 80cc465d8ac..97f4718382f 100644 --- a/drivers/hwmon/adm1029.c +++ b/drivers/hwmon/adm1029.c @@ -342,11 +342,10 @@ static int adm1029_probe(struct i2c_client *client, struct adm1029_data *data; int err; - data = kzalloc(sizeof(struct adm1029_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + 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); @@ -355,15 +354,13 @@ static int adm1029_probe(struct i2c_client *client, * Initialize the ADM1029 chip * Check config register */ - if (adm1029_init_client(client) == 0) { - err = -ENODEV; - goto exit_free; - } + if (adm1029_init_client(client) == 0) + return -ENODEV; /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &adm1029_group); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -375,9 +372,6 @@ static int adm1029_probe(struct i2c_client *client, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &adm1029_group); - exit_free: - kfree(data); - exit: return err; } @@ -405,7 +399,6 @@ static int adm1029_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adm1029_group); - kfree(data); return 0; } diff --git a/drivers/hwmon/adm9240.c b/drivers/hwmon/adm9240.c index 5a78d102a0f..8b24d1a4a2b 100644 --- a/drivers/hwmon/adm9240.c +++ b/drivers/hwmon/adm9240.c @@ -500,31 +500,6 @@ static ssize_t set_aout(struct device *dev, } static DEVICE_ATTR(aout_output, S_IRUGO | S_IWUSR, show_aout, set_aout); -/* chassis_clear */ -static ssize_t chassis_clear_legacy(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - long val; - int err; - - err = kstrtol(buf, 10, &val); - if (err) - return err; - - dev_warn(dev, "Attribute chassis_clear is deprecated, " - "use intrusion0_alarm instead\n"); - - if (val == 1) { - i2c_smbus_write_byte_data(client, - ADM9240_REG_CHASSIS_CLEAR, 0x80); - dev_dbg(&client->dev, "chassis intrusion latch cleared\n"); - } - return count; -} -static DEVICE_ATTR(chassis_clear, S_IWUSR, NULL, chassis_clear_legacy); - static ssize_t chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) @@ -586,7 +561,6 @@ static struct attribute *adm9240_attributes[] = { &sensor_dev_attr_fan2_alarm.dev_attr.attr, &dev_attr_alarms.attr, &dev_attr_aout_output.attr, - &dev_attr_chassis_clear.attr, &sensor_dev_attr_intrusion0_alarm.dev_attr.attr, &dev_attr_cpu0_vid.attr, NULL diff --git a/drivers/hwmon/ads1015.c b/drivers/hwmon/ads1015.c index 1958f03efd7..2798246ad81 100644 --- a/drivers/hwmon/ads1015.c +++ b/drivers/hwmon/ads1015.c @@ -156,7 +156,6 @@ static int ads1015_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); for (k = 0; k < ADS1015_CHANNELS; ++k) device_remove_file(&client->dev, &ads1015_in[k].dev_attr); - kfree(data); return 0; } @@ -254,11 +253,10 @@ static int ads1015_probe(struct i2c_client *client, int err; unsigned int k; - data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct ads1015_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -284,8 +282,6 @@ static int ads1015_probe(struct i2c_client *client, exit_remove: for (k = 0; k < ADS1015_CHANNELS; ++k) device_remove_file(&client->dev, &ads1015_in[k].dev_attr); - kfree(data); -exit: return err; } diff --git a/drivers/hwmon/ads7828.c b/drivers/hwmon/ads7828.c index bf3fdf49559..1f9e8af0f32 100644 --- a/drivers/hwmon/ads7828.c +++ b/drivers/hwmon/ads7828.c @@ -154,7 +154,6 @@ static int ads7828_remove(struct i2c_client *client) struct ads7828_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &ads7828_group); - kfree(i2c_get_clientdata(client)); return 0; } @@ -217,11 +216,10 @@ static int ads7828_probe(struct i2c_client *client, struct ads7828_data *data; int err; - data = kzalloc(sizeof(struct ads7828_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct ads7828_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -229,7 +227,7 @@ static int ads7828_probe(struct i2c_client *client, /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &ads7828_group); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -241,9 +239,6 @@ static int ads7828_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &ads7828_group); -exit_free: - kfree(data); -exit: return err; } diff --git a/drivers/hwmon/ads7871.c b/drivers/hwmon/ads7871.c index 7bf4ce3d405..1b53aa42b6d 100644 --- a/drivers/hwmon/ads7871.c +++ b/drivers/hwmon/ads7871.c @@ -198,20 +198,17 @@ static int __devinit ads7871_probe(struct spi_device *spi) * because there is no other error checking on an SPI bus * we need to make sure we really have a chip */ - if (val != ret) { - err = -ENODEV; - goto exit; - } + if (val != ret) + return -ENODEV; - pdata = kzalloc(sizeof(struct ads7871_data), GFP_KERNEL); - if (!pdata) { - err = -ENOMEM; - goto exit; - } + pdata = devm_kzalloc(&spi->dev, sizeof(struct ads7871_data), + GFP_KERNEL); + if (!pdata) + return -ENOMEM; err = sysfs_create_group(&spi->dev.kobj, &ads7871_group); if (err < 0) - goto error_free; + return err; spi_set_drvdata(spi, pdata); @@ -225,9 +222,6 @@ static int __devinit ads7871_probe(struct spi_device *spi) error_remove: sysfs_remove_group(&spi->dev.kobj, &ads7871_group); -error_free: - kfree(pdata); -exit: return err; } @@ -237,7 +231,6 @@ static int __devexit ads7871_remove(struct spi_device *spi) hwmon_device_unregister(pdata->hwmon_dev); sysfs_remove_group(&spi->dev.kobj, &ads7871_group); - kfree(pdata); return 0; } diff --git a/drivers/hwmon/adt7410.c b/drivers/hwmon/adt7410.c new file mode 100644 index 00000000000..030c8d7c33a --- /dev/null +++ b/drivers/hwmon/adt7410.c @@ -0,0 +1,464 @@ +/* + * adt7410.c - Part of lm_sensors, Linux kernel modules for hardware + * monitoring + * This driver handles the ADT7410 and compatible digital temperature sensors. + * Hartmut Knaack <knaack.h@gmx.de> 2012-07-22 + * based on lm75.c by Frodo Looijaard <frodol@dds.nl> + * and adt7410.c from iio-staging by Sonic Zhang <sonic.zhang@analog.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <linux/module.h> +#include <linux/init.h> +#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> + +/* + * ADT7410 registers definition + */ + +#define ADT7410_TEMPERATURE 0 +#define ADT7410_STATUS 2 +#define ADT7410_CONFIG 3 +#define ADT7410_T_ALARM_HIGH 4 +#define ADT7410_T_ALARM_LOW 6 +#define ADT7410_T_CRIT 8 +#define ADT7410_T_HYST 0xA + +/* + * ADT7410 status + */ +#define ADT7410_STAT_T_LOW (1 << 4) +#define ADT7410_STAT_T_HIGH (1 << 5) +#define ADT7410_STAT_T_CRIT (1 << 6) +#define ADT7410_STAT_NOT_RDY (1 << 7) + +/* + * ADT7410 config + */ +#define ADT7410_FAULT_QUEUE_MASK (1 << 0 | 1 << 1) +#define ADT7410_CT_POLARITY (1 << 2) +#define ADT7410_INT_POLARITY (1 << 3) +#define ADT7410_EVENT_MODE (1 << 4) +#define ADT7410_MODE_MASK (1 << 5 | 1 << 6) +#define ADT7410_FULL (0 << 5 | 0 << 6) +#define ADT7410_PD (1 << 5 | 1 << 6) +#define ADT7410_RESOLUTION (1 << 7) + +/* + * ADT7410 masks + */ +#define ADT7410_T13_VALUE_MASK 0xFFF8 +#define ADT7410_T_HYST_MASK 0xF + +/* straight from the datasheet */ +#define ADT7410_TEMP_MIN (-55000) +#define ADT7410_TEMP_MAX 150000 + +enum adt7410_type { /* keep sorted in alphabetical order */ + adt7410, +}; + +/* Addresses scanned */ +static const unsigned short normal_i2c[] = { 0x48, 0x49, 0x4a, 0x4b, + I2C_CLIENT_END }; + +static const u8 ADT7410_REG_TEMP[4] = { + ADT7410_TEMPERATURE, /* input */ + ADT7410_T_ALARM_HIGH, /* high */ + ADT7410_T_ALARM_LOW, /* low */ + ADT7410_T_CRIT, /* critical */ +}; + +/* Each client has this additional data */ +struct adt7410_data { + struct device *hwmon_dev; + struct mutex update_lock; + u8 config; + u8 oldconfig; + bool valid; /* true if registers valid */ + unsigned long last_updated; /* In jiffies */ + s16 temp[4]; /* Register values, + 0 = input + 1 = high + 2 = low + 3 = critical */ + u8 hyst; /* hysteresis offset */ +}; + +/* + * adt7410 register access by I2C + */ +static int adt7410_temp_ready(struct i2c_client *client) +{ + int i, status; + + for (i = 0; i < 6; i++) { + status = i2c_smbus_read_byte_data(client, ADT7410_STATUS); + if (status < 0) + return status; + if (!(status & ADT7410_STAT_NOT_RDY)) + return 0; + msleep(60); + } + return -ETIMEDOUT; +} + +static struct adt7410_data *adt7410_update_device(struct device *dev) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7410_data *data = i2c_get_clientdata(client); + struct adt7410_data *ret = data; + mutex_lock(&data->update_lock); + + if (time_after(jiffies, data->last_updated + HZ + HZ / 2) + || !data->valid) { + int i, status; + + dev_dbg(&client->dev, "Starting update\n"); + + status = adt7410_temp_ready(client); /* check for new value */ + if (unlikely(status)) { + ret = ERR_PTR(status); + goto abort; + } + for (i = 0; i < ARRAY_SIZE(data->temp); i++) { + status = i2c_smbus_read_word_swapped(client, + ADT7410_REG_TEMP[i]); + if (unlikely(status < 0)) { + dev_dbg(dev, + "Failed to read value: reg %d, error %d\n", + ADT7410_REG_TEMP[i], status); + ret = ERR_PTR(status); + goto abort; + } + data->temp[i] = status; + } + status = i2c_smbus_read_byte_data(client, ADT7410_T_HYST); + if (unlikely(status < 0)) { + dev_dbg(dev, + "Failed to read value: reg %d, error %d\n", + ADT7410_T_HYST, status); + ret = ERR_PTR(status); + goto abort; + } + data->hyst = status; + data->last_updated = jiffies; + data->valid = true; + } + +abort: + mutex_unlock(&data->update_lock); + return ret; +} + +static s16 ADT7410_TEMP_TO_REG(long temp) +{ + return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, ADT7410_TEMP_MIN, + ADT7410_TEMP_MAX) * 128, 1000); +} + +static int ADT7410_REG_TO_TEMP(struct adt7410_data *data, s16 reg) +{ + /* in 13 bit mode, bits 0-2 are status flags - mask them out */ + if (!(data->config & ADT7410_RESOLUTION)) + reg &= ADT7410_T13_VALUE_MASK; + /* + * temperature is stored in twos complement format, in steps of + * 1/128°C + */ + return DIV_ROUND_CLOSEST(reg * 1000, 128); +} + +/*-----------------------------------------------------------------------*/ + +/* sysfs attributes for hwmon */ + +static ssize_t adt7410_show_temp(struct device *dev, + struct device_attribute *da, char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct adt7410_data *data = adt7410_update_device(dev); + + if (IS_ERR(data)) + return PTR_ERR(data); + + return sprintf(buf, "%d\n", ADT7410_REG_TO_TEMP(data, + data->temp[attr->index])); +} + +static ssize_t adt7410_set_temp(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct i2c_client *client = to_i2c_client(dev); + struct adt7410_data *data = i2c_get_clientdata(client); + int nr = attr->index; + long temp; + int ret; + + ret = kstrtol(buf, 10, &temp); + if (ret) + return ret; + + mutex_lock(&data->update_lock); + data->temp[nr] = ADT7410_TEMP_TO_REG(temp); + ret = i2c_smbus_write_word_swapped(client, ADT7410_REG_TEMP[nr], + data->temp[nr]); + if (ret) + count = ret; + mutex_unlock(&data->update_lock); + return count; +} + +static ssize_t adt7410_show_t_hyst(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + struct adt7410_data *data; + int nr = attr->index; + int hyst; + + data = adt7410_update_device(dev); + if (IS_ERR(data)) + return PTR_ERR(data); + hyst = (data->hyst & ADT7410_T_HYST_MASK) * 1000; + + /* + * hysteresis is stored as a 4 bit offset in the device, convert it + * to an absolute value + */ + if (nr == 2) /* min has positive offset, others have negative */ + hyst = -hyst; + return sprintf(buf, "%d\n", + ADT7410_REG_TO_TEMP(data, data->temp[nr]) - hyst); +} + +static ssize_t adt7410_set_t_hyst(struct device *dev, + struct device_attribute *da, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct adt7410_data *data = i2c_get_clientdata(client); + int limit, ret; + long hyst; + + ret = kstrtol(buf, 10, &hyst); + if (ret) + return ret; + /* convert absolute hysteresis value to a 4 bit delta value */ + limit = ADT7410_REG_TO_TEMP(data, data->temp[1]); + hyst = SENSORS_LIMIT(hyst, ADT7410_TEMP_MIN, ADT7410_TEMP_MAX); + data->hyst = SENSORS_LIMIT(DIV_ROUND_CLOSEST(limit - hyst, 1000), + 0, ADT7410_T_HYST_MASK); + ret = i2c_smbus_write_byte_data(client, ADT7410_T_HYST, data->hyst); + if (ret) + return ret; + + return count; +} + +static ssize_t adt7410_show_alarm(struct device *dev, + struct device_attribute *da, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(da); + int ret; + + ret = i2c_smbus_read_byte_data(client, ADT7410_STATUS); + if (ret < 0) + return ret; + + return sprintf(buf, "%d\n", !!(ret & attr->index)); +} + +static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7410_show_temp, NULL, 0); +static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, + adt7410_show_temp, adt7410_set_temp, 1); +static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, + adt7410_show_temp, adt7410_set_temp, 2); +static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, + adt7410_show_temp, adt7410_set_temp, 3); +static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, + adt7410_show_t_hyst, adt7410_set_t_hyst, 1); +static SENSOR_DEVICE_ATTR(temp1_min_hyst, S_IRUGO, + adt7410_show_t_hyst, NULL, 2); +static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IRUGO, + adt7410_show_t_hyst, NULL, 3); +static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, adt7410_show_alarm, + NULL, ADT7410_STAT_T_LOW); +static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, adt7410_show_alarm, + NULL, ADT7410_STAT_T_HIGH); +static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, adt7410_show_alarm, + NULL, ADT7410_STAT_T_CRIT); + +static struct attribute *adt7410_attributes[] = { + &sensor_dev_attr_temp1_input.dev_attr.attr, + &sensor_dev_attr_temp1_max.dev_attr.attr, + &sensor_dev_attr_temp1_min.dev_attr.attr, + &sensor_dev_attr_temp1_crit.dev_attr.attr, + &sensor_dev_attr_temp1_max_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, + &sensor_dev_attr_temp1_min_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, + &sensor_dev_attr_temp1_crit_alarm.dev_attr.attr, + NULL +}; + +static const struct attribute_group adt7410_group = { + .attrs = adt7410_attributes, +}; + +/*-----------------------------------------------------------------------*/ + +/* device probe and removal */ + +static int adt7410_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct adt7410_data *data; + int ret; + + if (!i2c_check_functionality(client->adapter, + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) + return -ENODEV; + + data = devm_kzalloc(&client->dev, sizeof(struct adt7410_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; + + i2c_set_clientdata(client, data); + mutex_init(&data->update_lock); + + /* configure as specified */ + ret = i2c_smbus_read_byte_data(client, ADT7410_CONFIG); + if (ret < 0) { + dev_dbg(&client->dev, "Can't read config? %d\n", ret); + return ret; + } + data->oldconfig = ret; + /* + * Set to 16 bit resolution, continous conversion and comparator mode. + */ + data->config = ret | ADT7410_FULL | ADT7410_RESOLUTION | + ADT7410_EVENT_MODE; + if (data->config != data->oldconfig) { + ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, + data->config); + if (ret) + return ret; + } + dev_dbg(&client->dev, "Config %02x\n", data->config); + + /* Register sysfs hooks */ + ret = sysfs_create_group(&client->dev.kobj, &adt7410_group); + if (ret) + goto exit_restore; + + 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, "sensor '%s'\n", client->name); + + return 0; + +exit_remove: + sysfs_remove_group(&client->dev.kobj, &adt7410_group); +exit_restore: + i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->oldconfig); + return ret; +} + +static int adt7410_remove(struct i2c_client *client) +{ + struct adt7410_data *data = i2c_get_clientdata(client); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&client->dev.kobj, &adt7410_group); + if (data->oldconfig != data->config) + i2c_smbus_write_byte_data(client, ADT7410_CONFIG, + data->oldconfig); + return 0; +} + +static const struct i2c_device_id adt7410_ids[] = { + { "adt7410", adt7410, }, + { /* LIST END */ } +}; +MODULE_DEVICE_TABLE(i2c, adt7410_ids); + +#ifdef CONFIG_PM +static int adt7410_suspend(struct device *dev) +{ + int ret; + struct i2c_client *client = to_i2c_client(dev); + struct adt7410_data *data = i2c_get_clientdata(client); + + ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, + data->config | ADT7410_PD); + return ret; +} + +static int adt7410_resume(struct device *dev) +{ + int ret; + struct i2c_client *client = to_i2c_client(dev); + struct adt7410_data *data = i2c_get_clientdata(client); + + ret = i2c_smbus_write_byte_data(client, ADT7410_CONFIG, data->config); + return ret; +} + +static const struct dev_pm_ops adt7410_dev_pm_ops = { + .suspend = adt7410_suspend, + .resume = adt7410_resume, +}; +#define ADT7410_DEV_PM_OPS (&adt7410_dev_pm_ops) +#else +#define ADT7410_DEV_PM_OPS NULL +#endif /* CONFIG_PM */ + +static struct i2c_driver adt7410_driver = { + .class = I2C_CLASS_HWMON, + .driver = { + .name = "adt7410", + .pm = ADT7410_DEV_PM_OPS, + }, + .probe = adt7410_probe, + .remove = adt7410_remove, + .id_table = adt7410_ids, + .address_list = normal_i2c, +}; + +module_i2c_driver(adt7410_driver); + +MODULE_AUTHOR("Hartmut Knaack"); +MODULE_DESCRIPTION("ADT7410 driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c index 71bacc56e13..fe72c69a2d6 100644 --- a/drivers/hwmon/adt7411.c +++ b/drivers/hwmon/adt7411.c @@ -283,7 +283,7 @@ static int __devinit adt7411_probe(struct i2c_client *client, struct adt7411_data *data; int ret; - data = kzalloc(sizeof(*data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -294,14 +294,14 @@ static int __devinit adt7411_probe(struct i2c_client *client, ret = adt7411_modify_bit(client, ADT7411_REG_CFG1, ADT7411_CFG1_START_MONITOR, 1); if (ret < 0) - goto exit_free; + return ret; /* force update on first occasion */ data->next_update = jiffies; ret = sysfs_create_group(&client->dev.kobj, &adt7411_attr_grp); if (ret) - goto exit_free; + return ret; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -315,8 +315,6 @@ static int __devinit adt7411_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - exit_free: - kfree(data); return ret; } @@ -326,7 +324,6 @@ static int __devexit adt7411_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &adt7411_attr_grp); - kfree(data); return 0; } diff --git a/drivers/hwmon/adt7462.c b/drivers/hwmon/adt7462.c index 339269f76e5..baee482aedf 100644 --- a/drivers/hwmon/adt7462.c +++ b/drivers/hwmon/adt7462.c @@ -1931,11 +1931,10 @@ static int adt7462_probe(struct i2c_client *client, struct adt7462_data *data; int err; - data = kzalloc(sizeof(struct adt7462_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct adt7462_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->lock); @@ -1946,7 +1945,7 @@ static int adt7462_probe(struct i2c_client *client, data->attrs.attrs = adt7462_attr; err = sysfs_create_group(&client->dev.kobj, &data->attrs); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -1958,9 +1957,6 @@ static int adt7462_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &data->attrs); -exit_free: - kfree(data); -exit: return err; } @@ -1970,7 +1966,6 @@ static int adt7462_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); - kfree(data); return 0; } diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index 54ec890521f..39ecb1a3b9e 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c @@ -1256,11 +1256,10 @@ static int adt7470_probe(struct i2c_client *client, struct adt7470_data *data; int err; - data = kzalloc(sizeof(struct adt7470_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct adt7470_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; data->num_temp_sensors = -1; data->auto_update_interval = AUTO_UPDATE_INTERVAL; @@ -1277,7 +1276,7 @@ static int adt7470_probe(struct i2c_client *client, data->attrs.attrs = adt7470_attr; err = sysfs_create_group(&client->dev.kobj, &data->attrs); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -1299,9 +1298,6 @@ exit_unregister: hwmon_device_unregister(data->hwmon_dev); exit_remove: sysfs_remove_group(&client->dev.kobj, &data->attrs); -exit_free: - kfree(data); -exit: return err; } @@ -1313,7 +1309,6 @@ static int adt7470_remove(struct i2c_client *client) wait_for_completion(&data->auto_update_stop); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &data->attrs); - kfree(data); return 0; } diff --git a/drivers/hwmon/amc6821.c b/drivers/hwmon/amc6821.c index f600fa1f92e..ae482e3afda 100644 --- a/drivers/hwmon/amc6821.c +++ b/drivers/hwmon/amc6821.c @@ -862,12 +862,10 @@ static int amc6821_probe( struct amc6821_data *data; int err; - data = kzalloc(sizeof(struct amc6821_data), GFP_KERNEL); - if (!data) { - dev_err(&client->dev, "out of memory.\n"); + 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); @@ -877,11 +875,11 @@ static int amc6821_probe( */ err = amc6821_init_client(client); if (err) - goto err_free; + return err; err = sysfs_create_group(&client->dev.kobj, &amc6821_attr_grp); if (err) - goto err_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (!IS_ERR(data->hwmon_dev)) @@ -890,8 +888,6 @@ static int amc6821_probe( err = PTR_ERR(data->hwmon_dev); dev_err(&client->dev, "error registering hwmon device.\n"); sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); -err_free: - kfree(data); return err; } @@ -902,8 +898,6 @@ static int amc6821_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &amc6821_attr_grp); - kfree(data); - return 0; } diff --git a/drivers/hwmon/asb100.c b/drivers/hwmon/asb100.c index 4b8814deabb..a227be47149 100644 --- a/drivers/hwmon/asb100.c +++ b/drivers/hwmon/asb100.c @@ -787,12 +787,10 @@ static int asb100_probe(struct i2c_client *client, int err; struct asb100_data *data; - data = kzalloc(sizeof(struct asb100_data), GFP_KERNEL); - if (!data) { - pr_debug("probe failed, kzalloc failed!\n"); - err = -ENOMEM; - goto ERROR0; - } + data = devm_kzalloc(&client->dev, sizeof(struct asb100_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->lock); @@ -801,7 +799,7 @@ static int asb100_probe(struct i2c_client *client, /* Attach secondary lm75 clients */ err = asb100_detect_subclients(client); if (err) - goto ERROR1; + return err; /* Initialize the chip */ asb100_init_client(client); @@ -829,9 +827,6 @@ ERROR4: ERROR3: i2c_unregister_device(data->lm75[1]); i2c_unregister_device(data->lm75[0]); -ERROR1: - kfree(data); -ERROR0: return err; } @@ -845,8 +840,6 @@ static int asb100_remove(struct i2c_client *client) i2c_unregister_device(data->lm75[1]); i2c_unregister_device(data->lm75[0]); - kfree(data); - return 0; } diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c index 4ee57894872..cccb0e9d45b 100644 --- a/drivers/hwmon/asus_atk0110.c +++ b/drivers/hwmon/asus_atk0110.c @@ -962,7 +962,6 @@ static int atk_add_sensor(struct atk_data *data, union acpi_object *obj) return 1; out: - kfree(sensor->acpi_name); kfree(sensor); return err; } diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c index e7c6a19f3b2..fe0eeec0b75 100644 --- a/drivers/hwmon/dme1737.c +++ b/drivers/hwmon/dme1737.c @@ -2475,11 +2475,9 @@ static int dme1737_i2c_probe(struct i2c_client *client, struct device *dev = &client->dev; int err; - data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(dev, sizeof(struct dme1737_data), GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); data->type = id->driver_data; @@ -2491,14 +2489,14 @@ static int dme1737_i2c_probe(struct i2c_client *client, err = dme1737_init_device(dev); if (err) { dev_err(dev, "Failed to initialize device.\n"); - goto exit_kfree; + return err; } /* Create sysfs files */ err = dme1737_create_files(dev); if (err) { dev_err(dev, "Failed to create sysfs files.\n"); - goto exit_kfree; + return err; } /* Register device */ @@ -2513,9 +2511,6 @@ static int dme1737_i2c_probe(struct i2c_client *client, exit_remove: dme1737_remove_files(dev); -exit_kfree: - kfree(data); -exit: return err; } @@ -2526,7 +2521,6 @@ static int dme1737_i2c_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); dme1737_remove_files(&client->dev); - kfree(data); return 0; } @@ -2645,19 +2639,16 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) int err; res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, DME1737_EXTENT, "dme1737")) { + if (!devm_request_region(dev, res->start, DME1737_EXTENT, "dme1737")) { dev_err(dev, "Failed to request region 0x%04x-0x%04x.\n", (unsigned short)res->start, (unsigned short)res->start + DME1737_EXTENT - 1); - err = -EBUSY; - goto exit; + return -EBUSY; } - data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release_region; - } + data = devm_kzalloc(dev, sizeof(struct dme1737_data), GFP_KERNEL); + if (!data) + return -ENOMEM; data->addr = res->start; platform_set_drvdata(pdev, data); @@ -2683,8 +2674,7 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) (device == SCH5127_DEVICE)) { data->type = sch5127; } else { - err = -ENODEV; - goto exit_kfree; + return -ENODEV; } } @@ -2703,14 +2693,14 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) err = dme1737_init_device(dev); if (err) { dev_err(dev, "Failed to initialize device.\n"); - goto exit_kfree; + return err; } /* Create sysfs files */ err = dme1737_create_files(dev); if (err) { dev_err(dev, "Failed to create sysfs files.\n"); - goto exit_kfree; + return err; } /* Register device */ @@ -2725,12 +2715,6 @@ static int __devinit dme1737_isa_probe(struct platform_device *pdev) exit_remove_files: dme1737_remove_files(dev); -exit_kfree: - platform_set_drvdata(pdev, NULL); - kfree(data); -exit_release_region: - release_region(res->start, DME1737_EXTENT); -exit: return err; } @@ -2740,9 +2724,6 @@ static int __devexit dme1737_isa_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); dme1737_remove_files(&pdev->dev); - release_region(data->addr, DME1737_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); return 0; } diff --git a/drivers/hwmon/ds620.c b/drivers/hwmon/ds620.c index 50663efad41..f1d6b422cf0 100644 --- a/drivers/hwmon/ds620.c +++ b/drivers/hwmon/ds620.c @@ -232,11 +232,10 @@ static int ds620_probe(struct i2c_client *client, struct ds620_data *data; int err; - data = kzalloc(sizeof(struct ds620_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct ds620_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -247,7 +246,7 @@ static int ds620_probe(struct i2c_client *client, /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &ds620_group); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -261,9 +260,6 @@ static int ds620_probe(struct i2c_client *client, exit_remove_files: sysfs_remove_group(&client->dev.kobj, &ds620_group); -exit_free: - kfree(data); -exit: return err; } @@ -274,8 +270,6 @@ static int ds620_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &ds620_group); - kfree(data); - return 0; } diff --git a/drivers/hwmon/emc1403.c b/drivers/hwmon/emc1403.c index 149dcb0e148..68ab94bde3f 100644 --- a/drivers/hwmon/emc1403.c +++ b/drivers/hwmon/emc1403.c @@ -306,11 +306,10 @@ static int emc1403_probe(struct i2c_client *client, int res; struct thermal_data *data; - data = kzalloc(sizeof(struct thermal_data), GFP_KERNEL); - if (data == NULL) { - dev_warn(&client->dev, "out of memory"); + data = devm_kzalloc(&client->dev, sizeof(struct thermal_data), + GFP_KERNEL); + if (data == NULL) return -ENOMEM; - } i2c_set_clientdata(client, data); mutex_init(&data->mutex); @@ -319,21 +318,19 @@ static int emc1403_probe(struct i2c_client *client, res = sysfs_create_group(&client->dev.kobj, &m_thermal_gr); if (res) { dev_warn(&client->dev, "create group failed\n"); - goto thermal_error1; + return res; } data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { res = PTR_ERR(data->hwmon_dev); dev_warn(&client->dev, "register hwmon dev failed\n"); - goto thermal_error2; + goto thermal_error; } dev_info(&client->dev, "EMC1403 Thermal chip found\n"); - return res; + return 0; -thermal_error2: +thermal_error: sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); -thermal_error1: - kfree(data); return res; } @@ -343,7 +340,6 @@ static int emc1403_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &m_thermal_gr); - kfree(data); return 0; } diff --git a/drivers/hwmon/emc2103.c b/drivers/hwmon/emc2103.c index 7bb8e888692..77f434c5823 100644 --- a/drivers/hwmon/emc2103.c +++ b/drivers/hwmon/emc2103.c @@ -590,7 +590,8 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - data = kzalloc(sizeof(struct emc2103_data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(struct emc2103_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -608,7 +609,7 @@ emc2103_probe(struct i2c_client *client, const struct i2c_device_id *id) if (status < 0) { dev_dbg(&client->dev, "reg 0x%02x, err %d\n", REG_CONF1, status); - goto exit_free; + return status; } /* detect current state of hardware */ @@ -631,7 +632,7 @@ 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) - goto exit_free; + return status; if (data->temp_count >= 3) { status = sysfs_create_group(&client->dev.kobj, @@ -666,8 +667,6 @@ exit_remove_temp3: sysfs_remove_group(&client->dev.kobj, &emc2103_temp3_group); exit_remove: sysfs_remove_group(&client->dev.kobj, &emc2103_group); -exit_free: - kfree(data); return status; } @@ -685,7 +684,6 @@ static int emc2103_remove(struct i2c_client *client) sysfs_remove_group(&client->dev.kobj, &emc2103_group); - kfree(data); return 0; } diff --git a/drivers/hwmon/f71882fg.c b/drivers/hwmon/f71882fg.c index 6d1226365e3..50e4ce2d22d 100644 --- a/drivers/hwmon/f71882fg.c +++ b/drivers/hwmon/f71882fg.c @@ -2274,7 +2274,8 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) int err, i; u8 start_reg, reg; - data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct f71882fg_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -2288,13 +2289,11 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) start_reg = f71882fg_read8(data, F71882FG_REG_START); if (start_reg & 0x04) { dev_warn(&pdev->dev, "Hardware monitor is powered down\n"); - err = -ENODEV; - goto exit_free; + return -ENODEV; } if (!(start_reg & 0x03)) { dev_warn(&pdev->dev, "Hardware monitoring not activated\n"); - err = -ENODEV; - goto exit_free; + return -ENODEV; } /* Register sysfs interface files */ @@ -2422,8 +2421,6 @@ static int __devinit f71882fg_probe(struct platform_device *pdev) exit_unregister_sysfs: f71882fg_remove(pdev); /* Will unregister the sysfs files for us */ return err; /* f71882fg_remove() also frees our data */ -exit_free: - kfree(data); return err; } @@ -2525,17 +2522,13 @@ static int f71882fg_remove(struct platform_device *pdev) ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans); } } - - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; } -static int __init f71882fg_find(int sioaddr, unsigned short *address, - struct f71882fg_sio_data *sio_data) +static int __init f71882fg_find(int sioaddr, struct f71882fg_sio_data *sio_data) { u16 devid; + unsigned short address; int err = superio_enter(sioaddr); if (err) return err; @@ -2603,25 +2596,25 @@ static int __init f71882fg_find(int sioaddr, unsigned short *address, goto exit; } - *address = superio_inw(sioaddr, SIO_REG_ADDR); - if (*address == 0) { + address = superio_inw(sioaddr, SIO_REG_ADDR); + if (address == 0) { pr_warn("Base address not set\n"); err = -ENODEV; goto exit; } - *address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ + address &= ~(REGION_LENGTH - 1); /* Ignore 3 LSB */ - err = 0; + err = address; pr_info("Found %s chip at %#x, revision %d\n", - f71882fg_names[sio_data->type], (unsigned int)*address, + f71882fg_names[sio_data->type], (unsigned int)address, (int)superio_inb(sioaddr, SIO_REG_DEVREV)); exit: superio_exit(sioaddr); return err; } -static int __init f71882fg_device_add(unsigned short address, - const struct f71882fg_sio_data *sio_data) +static int __init f71882fg_device_add(int address, + const struct f71882fg_sio_data *sio_data) { struct resource res = { .start = address, @@ -2668,19 +2661,21 @@ exit_device_put: static int __init f71882fg_init(void) { - int err = -ENODEV; - unsigned short address; + int err; + int address; struct f71882fg_sio_data sio_data; memset(&sio_data, 0, sizeof(sio_data)); - if (f71882fg_find(0x2e, &address, &sio_data) && - f71882fg_find(0x4e, &address, &sio_data)) - goto exit; + address = f71882fg_find(0x2e, &sio_data); + if (address < 0) + address = f71882fg_find(0x4e, &sio_data); + if (address < 0) + return address; err = platform_driver_register(&f71882fg_driver); if (err) - goto exit; + return err; err = f71882fg_device_add(address, &sio_data); if (err) @@ -2690,7 +2685,6 @@ static int __init f71882fg_init(void) exit_driver: platform_driver_unregister(&f71882fg_driver); -exit: return err; } diff --git a/drivers/hwmon/f75375s.c b/drivers/hwmon/f75375s.c index ece4159bd45..f7dba229395 100644 --- a/drivers/hwmon/f75375s.c +++ b/drivers/hwmon/f75375s.c @@ -838,7 +838,8 @@ static int f75375_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - data = kzalloc(sizeof(struct f75375_data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(struct f75375_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -848,7 +849,7 @@ static int f75375_probe(struct i2c_client *client, err = sysfs_create_group(&client->dev.kobj, &f75375_group); if (err) - goto exit_free; + return err; if (data->kind != f75373) { err = sysfs_chmod_file(&client->dev.kobj, @@ -875,8 +876,6 @@ static int f75375_probe(struct i2c_client *client, exit_remove: sysfs_remove_group(&client->dev.kobj, &f75375_group); -exit_free: - kfree(data); return err; } @@ -885,7 +884,6 @@ static int f75375_remove(struct i2c_client *client) struct f75375_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &f75375_group); - kfree(data); return 0; } diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index af69073b3fe..68ad7d25551 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -198,7 +198,7 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev, const struct pci_device_id *id) { struct fam15h_power_data *data; - struct device *dev; + struct device *dev = &pdev->dev; int err; /* @@ -208,23 +208,19 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev, */ tweak_runavg_range(pdev); - if (!fam15h_power_is_internal_node0(pdev)) { - err = -ENODEV; - goto exit; - } + if (!fam15h_power_is_internal_node0(pdev)) + return -ENODEV; + + data = devm_kzalloc(dev, sizeof(struct fam15h_power_data), GFP_KERNEL); + if (!data) + return -ENOMEM; - data = kzalloc(sizeof(struct fam15h_power_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } fam15h_power_init_data(pdev, data); - dev = &pdev->dev; dev_set_drvdata(dev, data); err = sysfs_create_group(&dev->kobj, &fam15h_power_attr_group); if (err) - goto exit_free_data; + return err; data->hwmon_dev = hwmon_device_register(dev); if (IS_ERR(data->hwmon_dev)) { @@ -236,9 +232,6 @@ static int __devinit fam15h_power_probe(struct pci_dev *pdev, exit_remove_group: sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); -exit_free_data: - kfree(data); -exit: return err; } @@ -251,8 +244,6 @@ static void __devexit fam15h_power_remove(struct pci_dev *pdev) data = dev_get_drvdata(dev); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&dev->kobj, &fam15h_power_attr_group); - dev_set_drvdata(dev, NULL); - kfree(data); } static DEFINE_PCI_DEVICE_TABLE(fam15h_power_id_table) = { diff --git a/drivers/hwmon/g760a.c b/drivers/hwmon/g760a.c index ebcd2698e4d..8b2106f60ed 100644 --- a/drivers/hwmon/g760a.c +++ b/drivers/hwmon/g760a.c @@ -207,7 +207,8 @@ static int g760a_probe(struct i2c_client *client, I2C_FUNC_SMBUS_BYTE_DATA)) return -EIO; - data = kzalloc(sizeof(struct g760a_data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(struct g760a_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -223,7 +224,7 @@ static int g760a_probe(struct i2c_client *client, /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &g760a_group); if (err) - goto error_sysfs_create_group; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -235,9 +236,6 @@ static int g760a_probe(struct i2c_client *client, error_hwmon_device_register: sysfs_remove_group(&client->dev.kobj, &g760a_group); -error_sysfs_create_group: - kfree(data); - return err; } @@ -246,8 +244,6 @@ static int g760a_remove(struct i2c_client *client) struct g760a_data *data = i2c_get_clientdata(client); hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &g760a_group); - kfree(data); - return 0; } diff --git a/drivers/hwmon/ina2xx.c b/drivers/hwmon/ina2xx.c index 602148299f6..70717d4a5e8 100644 --- a/drivers/hwmon/ina2xx.c +++ b/drivers/hwmon/ina2xx.c @@ -5,10 +5,18 @@ * Zero Drift Bi-Directional Current/Power Monitor with I2C Interface * Datasheet: http://www.ti.com/product/ina219 * + * INA220: + * Bi-Directional Current/Power Monitor with I2C Interface + * Datasheet: http://www.ti.com/product/ina220 + * * INA226: * Bi-Directional Current/Power Monitor with I2C Interface * Datasheet: http://www.ti.com/product/ina226 * + * INA230: + * Bi-directional Current/Power Monitor with I2C Interface + * Datasheet: http://www.ti.com/product/ina230 + * * Copyright (C) 2012 Lothar Felten <l-felten@ti.com> * Thanks to Jan Volkering * @@ -57,18 +65,49 @@ enum ina2xx_ids { ina219, ina226 }; +struct ina2xx_config { + u16 config_default; + int calibration_factor; + int registers; + int shunt_div; + int bus_voltage_shift; + int bus_voltage_lsb; /* uV */ + int power_lsb; /* uW */ +}; + struct ina2xx_data { struct device *hwmon_dev; + const struct ina2xx_config *config; struct mutex update_lock; bool valid; unsigned long last_updated; int kind; - int registers; u16 regs[INA2XX_MAX_REGISTERS]; }; +static const struct ina2xx_config ina2xx_config[] = { + [ina219] = { + .config_default = INA219_CONFIG_DEFAULT, + .calibration_factor = 40960000, + .registers = INA219_REGISTERS, + .shunt_div = 100, + .bus_voltage_shift = 3, + .bus_voltage_lsb = 4000, + .power_lsb = 20000, + }, + [ina226] = { + .config_default = INA226_CONFIG_DEFAULT, + .calibration_factor = 5120000, + .registers = INA226_REGISTERS, + .shunt_div = 400, + .bus_voltage_shift = 0, + .bus_voltage_lsb = 1250, + .power_lsb = 25000, + }, +}; + static struct ina2xx_data *ina2xx_update_device(struct device *dev) { struct i2c_client *client = to_i2c_client(dev); @@ -85,7 +124,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev) dev_dbg(&client->dev, "Starting ina2xx update\n"); /* Read all registers */ - for (i = 0; i < data->registers; i++) { + for (i = 0; i < data->config->registers; i++) { int rv = i2c_smbus_read_word_swapped(client, i); if (rv < 0) { ret = ERR_PTR(rv); @@ -101,73 +140,26 @@ abort: return ret; } -static int ina219_get_value(struct ina2xx_data *data, u8 reg) +static int ina2xx_get_value(struct ina2xx_data *data, u8 reg) { - /* - * calculate exact value for the given register - * we assume default power-on reset settings: - * bus voltage range 32V - * gain = /8 - * adc 1 & 2 -> conversion time 532uS - * mode is continuous shunt and bus - * calibration value is INA219_CALIBRATION_VALUE - */ - int val = data->regs[reg]; + int val; switch (reg) { case INA2XX_SHUNT_VOLTAGE: - /* LSB=10uV. Convert to mV. */ - val = DIV_ROUND_CLOSEST(val, 100); + val = DIV_ROUND_CLOSEST(data->regs[reg], + data->config->shunt_div); break; case INA2XX_BUS_VOLTAGE: - /* LSB=4mV. Register is not right aligned, convert to mV. */ - val = (val >> 3) * 4; + val = (data->regs[reg] >> data->config->bus_voltage_shift) + * data->config->bus_voltage_lsb; + val = DIV_ROUND_CLOSEST(val, 1000); break; case INA2XX_POWER: - /* LSB=20mW. Convert to uW */ - val = val * 20 * 1000; - break; - case INA2XX_CURRENT: - /* LSB=1mA (selected). Is in mA */ - break; - default: - /* programmer goofed */ - WARN_ON_ONCE(1); - val = 0; - break; - } - - return val; -} - -static int ina226_get_value(struct ina2xx_data *data, u8 reg) -{ - /* - * calculate exact value for the given register - * we assume default power-on reset settings: - * bus voltage range 32V - * gain = /8 - * adc 1 & 2 -> conversion time 532uS - * mode is continuous shunt and bus - * calibration value is INA226_CALIBRATION_VALUE - */ - int val = data->regs[reg]; - - switch (reg) { - case INA2XX_SHUNT_VOLTAGE: - /* LSB=2.5uV. Convert to mV. */ - val = DIV_ROUND_CLOSEST(val, 400); - break; - case INA2XX_BUS_VOLTAGE: - /* LSB=1.25mV. Convert to mV. */ - val = val + DIV_ROUND_CLOSEST(val, 4); - break; - case INA2XX_POWER: - /* LSB=25mW. Convert to uW */ - val = val * 25 * 1000; + val = data->regs[reg] * data->config->power_lsb; break; case INA2XX_CURRENT: /* LSB=1mA (selected). Is in mA */ + val = data->regs[reg]; break; default: /* programmer goofed */ @@ -184,23 +176,12 @@ static ssize_t ina2xx_show_value(struct device *dev, { struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct ina2xx_data *data = ina2xx_update_device(dev); - int value = 0; if (IS_ERR(data)) return PTR_ERR(data); - switch (data->kind) { - case ina219: - value = ina219_get_value(data, attr->index); - break; - case ina226: - value = ina226_get_value(data, attr->index); - break; - default: - WARN_ON_ONCE(1); - break; - } - return snprintf(buf, PAGE_SIZE, "%d\n", value); + return snprintf(buf, PAGE_SIZE, "%d\n", + ina2xx_get_value(data, attr->index)); } /* shunt voltage */ @@ -238,7 +219,7 @@ static int ina2xx_probe(struct i2c_client *client, struct i2c_adapter *adapter = client->adapter; struct ina2xx_data *data; struct ina2xx_platform_data *pdata; - int ret = 0; + int ret; long shunt = 10000; /* default shunt value 10mOhms */ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) @@ -259,38 +240,15 @@ static int ina2xx_probe(struct i2c_client *client, /* set the device type */ data->kind = id->driver_data; + data->config = &ina2xx_config[data->kind]; - switch (data->kind) { - case ina219: - /* device configuration */ - i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, - INA219_CONFIG_DEFAULT); - - /* set current LSB to 1mA, shunt is in uOhms */ - /* (equation 13 in datasheet) */ - i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, - 40960000 / shunt); - dev_info(&client->dev, - "power monitor INA219 (Rshunt = %li uOhm)\n", shunt); - data->registers = INA219_REGISTERS; - break; - case ina226: - /* device configuration */ - i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, - INA226_CONFIG_DEFAULT); - - /* set current LSB to 1mA, shunt is in uOhms */ - /* (equation 1 in datasheet)*/ - i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, - 5120000 / shunt); - dev_info(&client->dev, - "power monitor INA226 (Rshunt = %li uOhm)\n", shunt); - data->registers = INA226_REGISTERS; - break; - default: - /* unknown device id */ - return -ENODEV; - } + /* device configuration */ + i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, + data->config->config_default); + /* set current LSB to 1mA, shunt is in uOhms */ + /* (equation 13 in datasheet) */ + i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, + data->config->calibration_factor / shunt); i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -305,6 +263,9 @@ static int ina2xx_probe(struct i2c_client *client, goto out_err_hwmon; } + dev_info(&client->dev, "power monitor %s (Rshunt = %li uOhm)\n", + id->name, shunt); + return 0; out_err_hwmon: @@ -324,7 +285,9 @@ static int ina2xx_remove(struct i2c_client *client) static const struct i2c_device_id ina2xx_id[] = { { "ina219", ina219 }, + { "ina220", ina219 }, { "ina226", ina226 }, + { "ina230", ina226 }, { } }; MODULE_DEVICE_TABLE(i2c, ina2xx_id); diff --git a/drivers/hwmon/jz4740-hwmon.c b/drivers/hwmon/jz4740-hwmon.c index 5253d23361d..dee9eec2036 100644 --- a/drivers/hwmon/jz4740-hwmon.c +++ b/drivers/hwmon/jz4740-hwmon.c @@ -20,6 +20,7 @@ #include <linux/mutex.h> #include <linux/platform_device.h> #include <linux/slab.h> +#include <linux/io.h> #include <linux/completion.h> #include <linux/mfd/core.h> @@ -106,42 +107,37 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) int ret; struct jz4740_hwmon *hwmon; - hwmon = kmalloc(sizeof(*hwmon), GFP_KERNEL); - if (!hwmon) { - dev_err(&pdev->dev, "Failed to allocate driver structure\n"); + hwmon = devm_kzalloc(&pdev->dev, sizeof(*hwmon), GFP_KERNEL); + if (!hwmon) return -ENOMEM; - } hwmon->cell = mfd_get_cell(pdev); hwmon->irq = platform_get_irq(pdev, 0); if (hwmon->irq < 0) { - ret = hwmon->irq; - dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret); - goto err_free; + dev_err(&pdev->dev, "Failed to get platform irq: %d\n", + hwmon->irq); + return hwmon->irq; } hwmon->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!hwmon->mem) { - ret = -ENOENT; dev_err(&pdev->dev, "Failed to get platform mmio resource\n"); - goto err_free; + return -ENOENT; } - hwmon->mem = request_mem_region(hwmon->mem->start, + hwmon->mem = devm_request_mem_region(&pdev->dev, hwmon->mem->start, resource_size(hwmon->mem), pdev->name); if (!hwmon->mem) { - ret = -EBUSY; dev_err(&pdev->dev, "Failed to request mmio memory region\n"); - goto err_free; + return -EBUSY; } - hwmon->base = ioremap_nocache(hwmon->mem->start, - resource_size(hwmon->mem)); + hwmon->base = devm_ioremap_nocache(&pdev->dev, hwmon->mem->start, + resource_size(hwmon->mem)); if (!hwmon->base) { - ret = -EBUSY; dev_err(&pdev->dev, "Failed to ioremap mmio memory\n"); - goto err_release_mem_region; + return -EBUSY; } init_completion(&hwmon->read_completion); @@ -149,17 +145,18 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hwmon); - ret = request_irq(hwmon->irq, jz4740_hwmon_irq, 0, pdev->name, hwmon); + ret = devm_request_irq(&pdev->dev, hwmon->irq, jz4740_hwmon_irq, 0, + pdev->name, hwmon); if (ret) { dev_err(&pdev->dev, "Failed to request irq: %d\n", ret); - goto err_iounmap; + return ret; } disable_irq(hwmon->irq); ret = sysfs_create_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); if (ret) { dev_err(&pdev->dev, "Failed to create sysfs group: %d\n", ret); - goto err_free_irq; + return ret; } hwmon->hwmon = hwmon_device_register(&pdev->dev); @@ -172,16 +169,6 @@ static int __devinit jz4740_hwmon_probe(struct platform_device *pdev) err_remove_file: sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); -err_free_irq: - free_irq(hwmon->irq, hwmon); -err_iounmap: - platform_set_drvdata(pdev, NULL); - iounmap(hwmon->base); -err_release_mem_region: - release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); -err_free: - kfree(hwmon); - return ret; } @@ -192,14 +179,6 @@ static int __devexit jz4740_hwmon_remove(struct platform_device *pdev) hwmon_device_unregister(hwmon->hwmon); sysfs_remove_group(&pdev->dev.kobj, &jz4740_hwmon_attr_group); - free_irq(hwmon->irq, hwmon); - - iounmap(hwmon->base); - release_mem_region(hwmon->mem->start, resource_size(hwmon->mem)); - - platform_set_drvdata(pdev, NULL); - kfree(hwmon); - return 0; } diff --git a/drivers/hwmon/lm70.c b/drivers/hwmon/lm70.c index 472f79521a9..2d1777a03ed 100644 --- a/drivers/hwmon/lm70.c +++ b/drivers/hwmon/lm70.c @@ -43,6 +43,8 @@ #define LM70_CHIP_LM70 0 /* original NS LM70 */ #define LM70_CHIP_TMP121 1 /* TI TMP121/TMP123 */ +#define LM70_CHIP_LM71 2 /* NS LM71 */ +#define LM70_CHIP_LM74 3 /* NS LM74 */ struct lm70 { struct device *hwmon_dev; @@ -88,9 +90,13 @@ static ssize_t lm70_sense_temp(struct device *dev, * Celsius. * So it's equivalent to multiplying by 0.25 * 1000 = 250. * - * TMP121/TMP123: + * LM74 and TMP121/TMP123: * 13 bits of 2's complement data, discard LSB 3 bits, * resolution 0.0625 degrees celsius. + * + * LM71: + * 14 bits of 2's complement data, discard LSB 2 bits, + * resolution 0.0312 degrees celsius. */ switch (p_lm70->chip) { case LM70_CHIP_LM70: @@ -98,8 +104,13 @@ static ssize_t lm70_sense_temp(struct device *dev, break; case LM70_CHIP_TMP121: + case LM70_CHIP_LM74: val = ((int)raw / 8) * 625 / 10; break; + + case LM70_CHIP_LM71: + val = ((int)raw / 4) * 3125 / 100; + break; } status = sprintf(buf, "%d\n", val); /* millidegrees Celsius */ @@ -113,20 +124,7 @@ static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); static ssize_t lm70_show_name(struct device *dev, struct device_attribute *devattr, char *buf) { - struct lm70 *p_lm70 = dev_get_drvdata(dev); - int ret; - - switch (p_lm70->chip) { - case LM70_CHIP_LM70: - ret = sprintf(buf, "lm70\n"); - break; - case LM70_CHIP_TMP121: - ret = sprintf(buf, "tmp121\n"); - break; - default: - ret = -EINVAL; - } - return ret; + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); } static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); @@ -139,17 +137,13 @@ static int __devinit lm70_probe(struct spi_device *spi) struct lm70 *p_lm70; int status; - /* signaling is SPI_MODE_0 for both LM70 and TMP121 */ + /* signaling is SPI_MODE_0 */ if (spi->mode & (SPI_CPOL | SPI_CPHA)) return -EINVAL; - /* 3-wire link (shared SI/SO) for LM70 */ - if (chip == LM70_CHIP_LM70 && !(spi->mode & SPI_3WIRE)) - return -EINVAL; - /* NOTE: we assume 8-bit words, and convert to 16 bits manually */ - p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); + p_lm70 = devm_kzalloc(&spi->dev, sizeof(*p_lm70), GFP_KERNEL); if (!p_lm70) return -ENOMEM; @@ -181,7 +175,6 @@ out_dev_create_file_failed: device_remove_file(&spi->dev, &dev_attr_temp1_input); out_dev_create_temp_file_failed: spi_set_drvdata(spi, NULL); - kfree(p_lm70); return status; } @@ -193,7 +186,6 @@ static int __devexit lm70_remove(struct spi_device *spi) device_remove_file(&spi->dev, &dev_attr_temp1_input); device_remove_file(&spi->dev, &dev_attr_name); spi_set_drvdata(spi, NULL); - kfree(p_lm70); return 0; } @@ -202,6 +194,8 @@ static int __devexit lm70_remove(struct spi_device *spi) static const struct spi_device_id lm70_ids[] = { { "lm70", LM70_CHIP_LM70 }, { "tmp121", LM70_CHIP_TMP121 }, + { "lm71", LM70_CHIP_LM71 }, + { "lm74", LM70_CHIP_LM74 }, { }, }; MODULE_DEVICE_TABLE(spi, lm70_ids); @@ -219,5 +213,5 @@ static struct spi_driver lm70_driver = { module_spi_driver(lm70_driver); MODULE_AUTHOR("Kaiwan N Billimoria"); -MODULE_DESCRIPTION("NS LM70 / TI TMP121/TMP123 Linux driver"); +MODULE_DESCRIPTION("NS LM70 and compatibles Linux driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c index bf946187bd3..c3d4255ed15 100644 --- a/drivers/hwmon/lm93.c +++ b/drivers/hwmon/lm93.c @@ -1830,7 +1830,7 @@ static ssize_t store_fan_smart_tach(struct device *dev, mutex_lock(&data->update_lock); /* sanity test, ignore the write otherwise */ - if (0 <= val && val <= 2) { + if (val <= 2) { /* can't enable if pwm freq is 22.5KHz */ if (val) { u8 ctl4 = lm93_read_byte(client, diff --git a/drivers/hwmon/lm95241.c b/drivers/hwmon/lm95241.c index bd8cdb7b96e..4b68fb2a31d 100644 --- a/drivers/hwmon/lm95241.c +++ b/drivers/hwmon/lm95241.c @@ -391,11 +391,10 @@ static int lm95241_probe(struct i2c_client *new_client, struct lm95241_data *data; int err; - data = kzalloc(sizeof(struct lm95241_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&new_client->dev, sizeof(struct lm95241_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(new_client, data); mutex_init(&data->update_lock); @@ -406,7 +405,7 @@ static int lm95241_probe(struct i2c_client *new_client, /* Register sysfs hooks */ err = sysfs_create_group(&new_client->dev.kobj, &lm95241_group); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -418,9 +417,6 @@ static int lm95241_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm95241_group); -exit_free: - kfree(data); -exit: return err; } @@ -431,7 +427,6 @@ static int lm95241_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm95241_group); - kfree(data); return 0; } diff --git a/drivers/hwmon/lm95245.c b/drivers/hwmon/lm95245.c index 9a46c106a24..2915fd90836 100644 --- a/drivers/hwmon/lm95245.c +++ b/drivers/hwmon/lm95245.c @@ -462,11 +462,10 @@ static int lm95245_probe(struct i2c_client *new_client, struct lm95245_data *data; int err; - data = kzalloc(sizeof(struct lm95245_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&new_client->dev, sizeof(struct lm95245_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(new_client, data); mutex_init(&data->update_lock); @@ -477,7 +476,7 @@ static int lm95245_probe(struct i2c_client *new_client, /* Register sysfs hooks */ err = sysfs_create_group(&new_client->dev.kobj, &lm95245_group); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&new_client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -489,9 +488,6 @@ static int lm95245_probe(struct i2c_client *new_client, exit_remove_files: sysfs_remove_group(&new_client->dev.kobj, &lm95245_group); -exit_free: - kfree(data); -exit: return err; } @@ -502,7 +498,6 @@ static int lm95245_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &lm95245_group); - kfree(data); return 0; } diff --git a/drivers/hwmon/ltc4151.c b/drivers/hwmon/ltc4151.c index 4d005b219de..8496baa08bc 100644 --- a/drivers/hwmon/ltc4151.c +++ b/drivers/hwmon/ltc4151.c @@ -181,11 +181,9 @@ static int ltc4151_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto out_kzalloc; - } + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -193,7 +191,7 @@ static int ltc4151_probe(struct i2c_client *client, /* Register sysfs hooks */ ret = sysfs_create_group(&client->dev.kobj, <c4151_group); if (ret) - goto out_sysfs_create_group; + return ret; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -205,9 +203,6 @@ static int ltc4151_probe(struct i2c_client *client, out_hwmon_device_register: sysfs_remove_group(&client->dev.kobj, <c4151_group); -out_sysfs_create_group: - kfree(data); -out_kzalloc: return ret; } @@ -218,8 +213,6 @@ static int ltc4151_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, <c4151_group); - kfree(data); - return 0; } diff --git a/drivers/hwmon/ltc4215.c b/drivers/hwmon/ltc4215.c index 429c5b2b66f..98b3d04f98b 100644 --- a/drivers/hwmon/ltc4215.c +++ b/drivers/hwmon/ltc4215.c @@ -253,11 +253,9 @@ static int ltc4215_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto out_kzalloc; - } + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -268,7 +266,7 @@ static int ltc4215_probe(struct i2c_client *client, /* Register sysfs hooks */ ret = sysfs_create_group(&client->dev.kobj, <c4215_group); if (ret) - goto out_sysfs_create_group; + return ret; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -280,9 +278,6 @@ static int ltc4215_probe(struct i2c_client *client, out_hwmon_device_register: sysfs_remove_group(&client->dev.kobj, <c4215_group); -out_sysfs_create_group: - kfree(data); -out_kzalloc: return ret; } @@ -293,8 +288,6 @@ static int ltc4215_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, <c4215_group); - kfree(data); - return 0; } diff --git a/drivers/hwmon/ltc4245.c b/drivers/hwmon/ltc4245.c index b99b45bafda..52075914eb0 100644 --- a/drivers/hwmon/ltc4245.c +++ b/drivers/hwmon/ltc4245.c @@ -519,11 +519,9 @@ static int ltc4245_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - data = kzalloc(sizeof(*data), GFP_KERNEL); - if (!data) { - ret = -ENOMEM; - goto out_kzalloc; - } + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -536,7 +534,7 @@ static int ltc4245_probe(struct i2c_client *client, /* Register sysfs hooks */ ret = ltc4245_sysfs_create_groups(client); if (ret) - goto out_sysfs_create_groups; + return ret; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -548,9 +546,6 @@ static int ltc4245_probe(struct i2c_client *client, out_hwmon_device_register: ltc4245_sysfs_remove_groups(client); -out_sysfs_create_groups: - kfree(data); -out_kzalloc: return ret; } @@ -560,7 +555,6 @@ static int ltc4245_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); ltc4245_sysfs_remove_groups(client); - kfree(data); return 0; } diff --git a/drivers/hwmon/max1111.c b/drivers/hwmon/max1111.c index f3978a46e84..b4eb0889c46 100644 --- a/drivers/hwmon/max1111.c +++ b/drivers/hwmon/max1111.c @@ -22,6 +22,8 @@ #include <linux/spi/spi.h> #include <linux/slab.h> +enum chips { max1110, max1111, max1112, max1113 }; + #define MAX1111_TX_BUF_SIZE 1 #define MAX1111_RX_BUF_SIZE 2 @@ -30,6 +32,7 @@ #define MAX1111_CTRL_PD1 (1u << 1) #define MAX1111_CTRL_SGL (1u << 2) #define MAX1111_CTRL_UNI (1u << 3) +#define MAX1110_CTRL_SEL_SH (4) #define MAX1111_CTRL_SEL_SH (5) /* NOTE: bit 4 is ignored */ #define MAX1111_CTRL_STR (1u << 7) @@ -42,6 +45,8 @@ struct max1111_data { uint8_t rx_buf[MAX1111_RX_BUF_SIZE]; struct mutex drvdata_lock; /* protect msg, xfer and buffers from multiple access */ + int sel_sh; + int lsb; }; static int max1111_read(struct device *dev, int channel) @@ -53,7 +58,7 @@ static int max1111_read(struct device *dev, int channel) /* writing to drvdata struct is not thread safe, wait on mutex */ mutex_lock(&data->drvdata_lock); - data->tx_buf[0] = (channel << MAX1111_CTRL_SEL_SH) | + data->tx_buf[0] = (channel << data->sel_sh) | MAX1111_CTRL_PD0 | MAX1111_CTRL_PD1 | MAX1111_CTRL_SGL | MAX1111_CTRL_UNI | MAX1111_CTRL_STR; @@ -93,12 +98,13 @@ EXPORT_SYMBOL(max1111_read_channel); static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "max1111\n"); + return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); } static ssize_t show_adc(struct device *dev, struct device_attribute *attr, char *buf) { + struct max1111_data *data = dev_get_drvdata(dev); int channel = to_sensor_dev_attr(attr)->index; int ret; @@ -107,10 +113,10 @@ static ssize_t show_adc(struct device *dev, return ret; /* - * assume the reference voltage to be 2.048V, with an 8-bit sample, - * the LSB weight is 8mV + * Assume the reference voltage to be 2.048V or 4.096V, with an 8-bit + * sample. The LSB weight is 8mV or 16mV depending on the chip type. */ - return sprintf(buf, "%d\n", ret * 8); + return sprintf(buf, "%d\n", ret * data->lsb); } #define MAX1111_ADC_ATTR(_id) \ @@ -121,6 +127,10 @@ static MAX1111_ADC_ATTR(0); static MAX1111_ADC_ATTR(1); static MAX1111_ADC_ATTR(2); static MAX1111_ADC_ATTR(3); +static MAX1111_ADC_ATTR(4); +static MAX1111_ADC_ATTR(5); +static MAX1111_ADC_ATTR(6); +static MAX1111_ADC_ATTR(7); static struct attribute *max1111_attributes[] = { &dev_attr_name.attr, @@ -135,6 +145,18 @@ static const struct attribute_group max1111_attr_group = { .attrs = max1111_attributes, }; +static struct attribute *max1110_attributes[] = { + &sensor_dev_attr_in4_input.dev_attr.attr, + &sensor_dev_attr_in5_input.dev_attr.attr, + &sensor_dev_attr_in6_input.dev_attr.attr, + &sensor_dev_attr_in7_input.dev_attr.attr, + NULL, +}; + +static const struct attribute_group max1110_attr_group = { + .attrs = max1110_attributes, +}; + static int __devinit setup_transfer(struct max1111_data *data) { struct spi_message *m; @@ -159,6 +181,7 @@ static int __devinit setup_transfer(struct max1111_data *data) static int __devinit max1111_probe(struct spi_device *spi) { + enum chips chip = spi_get_device_id(spi)->driver_data; struct max1111_data *data; int err; @@ -174,6 +197,24 @@ static int __devinit max1111_probe(struct spi_device *spi) return -ENOMEM; } + switch (chip) { + case max1110: + data->lsb = 8; + data->sel_sh = MAX1110_CTRL_SEL_SH; + break; + case max1111: + data->lsb = 8; + data->sel_sh = MAX1111_CTRL_SEL_SH; + break; + case max1112: + data->lsb = 16; + data->sel_sh = MAX1110_CTRL_SEL_SH; + break; + case max1113: + data->lsb = 16; + data->sel_sh = MAX1111_CTRL_SEL_SH; + break; + } err = setup_transfer(data); if (err) return err; @@ -188,6 +229,14 @@ static int __devinit max1111_probe(struct spi_device *spi) dev_err(&spi->dev, "failed to create attribute group\n"); return err; } + if (chip == max1110 || chip == max1112) { + err = sysfs_create_group(&spi->dev.kobj, &max1110_attr_group); + if (err) { + dev_err(&spi->dev, + "failed to create extended attribute group\n"); + goto err_remove; + } + } data->hwmon_dev = hwmon_device_register(&spi->dev); if (IS_ERR(data->hwmon_dev)) { @@ -202,6 +251,7 @@ static int __devinit max1111_probe(struct spi_device *spi) return 0; err_remove: + sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); return err; } @@ -211,16 +261,27 @@ static int __devexit max1111_remove(struct spi_device *spi) struct max1111_data *data = spi_get_drvdata(spi); hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&spi->dev.kobj, &max1110_attr_group); sysfs_remove_group(&spi->dev.kobj, &max1111_attr_group); mutex_destroy(&data->drvdata_lock); return 0; } +static const struct spi_device_id max1111_ids[] = { + { "max1110", max1110 }, + { "max1111", max1111 }, + { "max1112", max1112 }, + { "max1113", max1113 }, + { }, +}; +MODULE_DEVICE_TABLE(spi, max1111_ids); + static struct spi_driver max1111_driver = { .driver = { .name = "max1111", .owner = THIS_MODULE, }, + .id_table = max1111_ids, .probe = max1111_probe, .remove = __devexit_p(max1111_remove), }; @@ -228,6 +289,5 @@ static struct spi_driver max1111_driver = { module_spi_driver(max1111_driver); MODULE_AUTHOR("Eric Miao <eric.miao@marvell.com>"); -MODULE_DESCRIPTION("MAX1111 ADC Driver"); +MODULE_DESCRIPTION("MAX1110/MAX1111/MAX1112/MAX1113 ADC Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:max1111"); diff --git a/drivers/hwmon/max1668.c b/drivers/hwmon/max1668.c index 335b183d7c0..666d9f6263e 100644 --- a/drivers/hwmon/max1668.c +++ b/drivers/hwmon/max1668.c @@ -411,7 +411,8 @@ static int max1668_probe(struct i2c_client *client, if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) return -ENODEV; - data = kzalloc(sizeof(struct max1668_data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(struct max1668_data), + GFP_KERNEL); if (!data) return -ENOMEM; @@ -422,7 +423,7 @@ static int max1668_probe(struct i2c_client *client, /* Register sysfs hooks */ err = sysfs_create_group(&client->dev.kobj, &max1668_group_common); if (err) - goto error_free; + return err; if (data->type == max1668 || data->type == max1989) { err = sysfs_create_group(&client->dev.kobj, @@ -444,8 +445,6 @@ error_sysrem1: sysfs_remove_group(&client->dev.kobj, &max1668_group_unique); error_sysrem0: sysfs_remove_group(&client->dev.kobj, &max1668_group_common); -error_free: - kfree(data); return err; } @@ -459,7 +458,6 @@ static int max1668_remove(struct i2c_client *client) sysfs_remove_group(&client->dev.kobj, &max1668_group_common); - kfree(data); return 0; } diff --git a/drivers/hwmon/max197.c b/drivers/hwmon/max197.c new file mode 100644 index 00000000000..6304f2616fa --- /dev/null +++ b/drivers/hwmon/max197.c @@ -0,0 +1,349 @@ +/* + * Maxim MAX197 A/D Converter driver + * + * Copyright (c) 2012 Savoir-faire Linux Inc. + * Vivien Didelot <vivien.didelot@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * For further information, see the Documentation/hwmon/max197 file. + */ + +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/init.h> +#include <linux/err.h> +#include <linux/slab.h> +#include <linux/mutex.h> +#include <linux/device.h> +#include <linux/sysfs.h> +#include <linux/hwmon.h> +#include <linux/hwmon-sysfs.h> +#include <linux/platform_device.h> +#include <linux/platform_data/max197.h> + +#define MAX199_LIMIT 4000 /* 4V */ +#define MAX197_LIMIT 10000 /* 10V */ + +#define MAX197_NUM_CH 8 /* 8 Analog Input Channels */ + +/* Control byte format */ +#define MAX197_BIP (1 << 3) /* Bipolarity */ +#define MAX197_RNG (1 << 4) /* Full range */ + +#define MAX197_SCALE 12207 /* Scale coefficient for raw data */ + +/* List of supported chips */ +enum max197_chips { max197, max199 }; + +/** + * struct max197_data - device instance specific data + * @pdata: Platform data. + * @hwmon_dev: The hwmon device. + * @lock: Read/Write mutex. + * @limit: Max range value (10V for MAX197, 4V for MAX199). + * @scale: Need to scale. + * @ctrl_bytes: Channels control byte. + */ +struct max197_data { + struct max197_platform_data *pdata; + struct device *hwmon_dev; + struct mutex lock; + int limit; + bool scale; + u8 ctrl_bytes[MAX197_NUM_CH]; +}; + +static inline void max197_set_unipolarity(struct max197_data *data, int channel) +{ + data->ctrl_bytes[channel] &= ~MAX197_BIP; +} + +static inline void max197_set_bipolarity(struct max197_data *data, int channel) +{ + data->ctrl_bytes[channel] |= MAX197_BIP; +} + +static inline void max197_set_half_range(struct max197_data *data, int channel) +{ + data->ctrl_bytes[channel] &= ~MAX197_RNG; +} + +static inline void max197_set_full_range(struct max197_data *data, int channel) +{ + data->ctrl_bytes[channel] |= MAX197_RNG; +} + +static inline bool max197_is_bipolar(struct max197_data *data, int channel) +{ + return data->ctrl_bytes[channel] & MAX197_BIP; +} + +static inline bool max197_is_full_range(struct max197_data *data, int channel) +{ + return data->ctrl_bytes[channel] & MAX197_RNG; +} + +/* Function called on read access on in{0,1,2,3,4,5,6,7}_{min,max} */ +static ssize_t max197_show_range(struct device *dev, + struct device_attribute *devattr, char *buf) +{ + struct max197_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + int channel = attr->index; + bool is_min = attr->nr; + int range; + + if (mutex_lock_interruptible(&data->lock)) + return -ERESTARTSYS; + + range = max197_is_full_range(data, channel) ? + data->limit : data->limit / 2; + if (is_min) { + if (max197_is_bipolar(data, channel)) + range = -range; + else + range = 0; + } + + mutex_unlock(&data->lock); + + return sprintf(buf, "%d\n", range); +} + +/* Function called on write access on in{0,1,2,3,4,5,6,7}_{min,max} */ +static ssize_t max197_store_range(struct device *dev, + struct device_attribute *devattr, + const char *buf, size_t count) +{ + struct max197_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr); + int channel = attr->index; + bool is_min = attr->nr; + long value; + int half = data->limit / 2; + int full = data->limit; + + if (kstrtol(buf, 10, &value)) + return -EINVAL; + + if (is_min) { + if (value <= -full) + value = -full; + else if (value < 0) + value = -half; + else + value = 0; + } else { + if (value >= full) + value = full; + else + value = half; + } + + if (mutex_lock_interruptible(&data->lock)) + return -ERESTARTSYS; + + if (value == 0) { + /* We can deduce only the polarity */ + max197_set_unipolarity(data, channel); + } else if (value == -half) { + max197_set_bipolarity(data, channel); + max197_set_half_range(data, channel); + } else if (value == -full) { + max197_set_bipolarity(data, channel); + max197_set_full_range(data, channel); + } else if (value == half) { + /* We can deduce only the range */ + max197_set_half_range(data, channel); + } else if (value == full) { + /* We can deduce only the range */ + max197_set_full_range(data, channel); + } + + mutex_unlock(&data->lock); + + return count; +} + +/* Function called on read access on in{0,1,2,3,4,5,6,7}_input */ +static ssize_t max197_show_input(struct device *dev, + struct device_attribute *devattr, + char *buf) +{ + struct max197_data *data = dev_get_drvdata(dev); + struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); + int channel = attr->index; + s32 value; + int ret; + + if (mutex_lock_interruptible(&data->lock)) + return -ERESTARTSYS; + + ret = data->pdata->convert(data->ctrl_bytes[channel]); + if (ret < 0) { + dev_err(dev, "conversion failed\n"); + goto unlock; + } + value = ret; + + /* + * Coefficient to apply on raw value. + * See Table 1. Full Scale and Zero Scale in the MAX197 datasheet. + */ + if (data->scale) { + value *= MAX197_SCALE; + if (max197_is_full_range(data, channel)) + value *= 2; + value /= 10000; + } + + ret = sprintf(buf, "%d\n", value); + +unlock: + mutex_unlock(&data->lock); + return ret; +} + +static ssize_t max197_show_name(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct platform_device *pdev = to_platform_device(dev); + return sprintf(buf, "%s\n", pdev->name); +} + +#define MAX197_SENSOR_DEVICE_ATTR_CH(chan) \ + static SENSOR_DEVICE_ATTR(in##chan##_input, S_IRUGO, \ + max197_show_input, NULL, chan); \ + static SENSOR_DEVICE_ATTR_2(in##chan##_min, S_IRUGO | S_IWUSR, \ + max197_show_range, \ + max197_store_range, \ + true, chan); \ + static SENSOR_DEVICE_ATTR_2(in##chan##_max, S_IRUGO | S_IWUSR, \ + max197_show_range, \ + max197_store_range, \ + false, chan) + +#define MAX197_SENSOR_DEV_ATTR_IN(chan) \ + &sensor_dev_attr_in##chan##_input.dev_attr.attr, \ + &sensor_dev_attr_in##chan##_max.dev_attr.attr, \ + &sensor_dev_attr_in##chan##_min.dev_attr.attr + +static DEVICE_ATTR(name, S_IRUGO, max197_show_name, NULL); + +MAX197_SENSOR_DEVICE_ATTR_CH(0); +MAX197_SENSOR_DEVICE_ATTR_CH(1); +MAX197_SENSOR_DEVICE_ATTR_CH(2); +MAX197_SENSOR_DEVICE_ATTR_CH(3); +MAX197_SENSOR_DEVICE_ATTR_CH(4); +MAX197_SENSOR_DEVICE_ATTR_CH(5); +MAX197_SENSOR_DEVICE_ATTR_CH(6); +MAX197_SENSOR_DEVICE_ATTR_CH(7); + +static const struct attribute_group max197_sysfs_group = { + .attrs = (struct attribute *[]) { + &dev_attr_name.attr, + MAX197_SENSOR_DEV_ATTR_IN(0), + MAX197_SENSOR_DEV_ATTR_IN(1), + MAX197_SENSOR_DEV_ATTR_IN(2), + MAX197_SENSOR_DEV_ATTR_IN(3), + MAX197_SENSOR_DEV_ATTR_IN(4), + MAX197_SENSOR_DEV_ATTR_IN(5), + MAX197_SENSOR_DEV_ATTR_IN(6), + MAX197_SENSOR_DEV_ATTR_IN(7), + NULL + }, +}; + +static int __devinit max197_probe(struct platform_device *pdev) +{ + int ch, ret; + struct max197_data *data; + struct max197_platform_data *pdata = pdev->dev.platform_data; + enum max197_chips chip = platform_get_device_id(pdev)->driver_data; + + if (pdata == NULL) { + dev_err(&pdev->dev, "no platform data supplied\n"); + return -EINVAL; + } + + if (pdata->convert == NULL) { + dev_err(&pdev->dev, "no convert function supplied\n"); + return -EINVAL; + } + + data = devm_kzalloc(&pdev->dev, sizeof(struct max197_data), GFP_KERNEL); + if (!data) { + dev_err(&pdev->dev, "devm_kzalloc failed\n"); + return -ENOMEM; + } + + data->pdata = pdata; + mutex_init(&data->lock); + + if (chip == max197) { + data->limit = MAX197_LIMIT; + data->scale = true; + } else { + data->limit = MAX199_LIMIT; + data->scale = false; + } + + for (ch = 0; ch < MAX197_NUM_CH; ch++) + data->ctrl_bytes[ch] = (u8) ch; + + platform_set_drvdata(pdev, data); + + ret = sysfs_create_group(&pdev->dev.kobj, &max197_sysfs_group); + if (ret) { + dev_err(&pdev->dev, "sysfs create group failed\n"); + return ret; + } + + data->hwmon_dev = hwmon_device_register(&pdev->dev); + if (IS_ERR(data->hwmon_dev)) { + ret = PTR_ERR(data->hwmon_dev); + dev_err(&pdev->dev, "hwmon device register failed\n"); + goto error; + } + + return 0; + +error: + sysfs_remove_group(&pdev->dev.kobj, &max197_sysfs_group); + return ret; +} + +static int __devexit max197_remove(struct platform_device *pdev) +{ + struct max197_data *data = platform_get_drvdata(pdev); + + hwmon_device_unregister(data->hwmon_dev); + sysfs_remove_group(&pdev->dev.kobj, &max197_sysfs_group); + + return 0; +} + +static struct platform_device_id max197_device_ids[] = { + { "max197", max197 }, + { "max199", max199 }, + { } +}; +MODULE_DEVICE_TABLE(platform, max197_device_ids); + +static struct platform_driver max197_driver = { + .driver = { + .name = "max197", + .owner = THIS_MODULE, + }, + .probe = max197_probe, + .remove = __devexit_p(max197_remove), + .id_table = max197_device_ids, +}; +module_platform_driver(max197_driver); + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Savoir-faire Linux Inc. <kernel@savoirfairelinux.com>"); +MODULE_DESCRIPTION("Maxim MAX197 A/D Converter driver"); diff --git a/drivers/hwmon/mcp3021.c b/drivers/hwmon/mcp3021.c index d0afc0cd3ff..eedb32292d6 100644 --- a/drivers/hwmon/mcp3021.c +++ b/drivers/hwmon/mcp3021.c @@ -1,8 +1,9 @@ /* - * mcp3021.c - driver for the Microchip MCP3021 chip + * mcp3021.c - driver for Microchip MCP3021 and MCP3221 * * Copyright (C) 2008-2009, 2012 Freescale Semiconductor, Inc. * Author: Mingkai Hu <Mingkai.hu@freescale.com> + * Reworked by Sven Schuchmann <schuchmann@schleissheimer.de> * * This driver export the value of analog input voltage to sysfs, the * voltage unit is mV. Through the sysfs interface, lm-sensors tool @@ -34,16 +35,31 @@ #define MCP3021_OUTPUT_RES 10 /* 10-bit resolution */ #define MCP3021_OUTPUT_SCALE 4 +#define MCP3221_SAR_SHIFT 0 +#define MCP3221_SAR_MASK 0xfff +#define MCP3221_OUTPUT_RES 12 /* 12-bit resolution */ +#define MCP3221_OUTPUT_SCALE 1 + +enum chips { + mcp3021, + mcp3221 +}; + /* * Client data (each client gets its own) */ struct mcp3021_data { struct device *hwmon_dev; u32 vdd; /* device power supply */ + u16 sar_shift; + u16 sar_mask; + u8 output_res; + u8 output_scale; }; static int mcp3021_read16(struct i2c_client *client) { + struct mcp3021_data *data = i2c_get_clientdata(client); int ret; u16 reg; __be16 buf; @@ -61,20 +77,20 @@ static int mcp3021_read16(struct i2c_client *client) * The ten-bit output code is composed of the lower 4-bit of the * first byte and the upper 6-bit of the second byte. */ - reg = (reg >> MCP3021_SAR_SHIFT) & MCP3021_SAR_MASK; + reg = (reg >> data->sar_shift) & data->sar_mask; return reg; } -static inline u16 volts_from_reg(u16 vdd, u16 val) +static inline u16 volts_from_reg(struct mcp3021_data *data, u16 val) { if (val == 0) return 0; - val = val * MCP3021_OUTPUT_SCALE - MCP3021_OUTPUT_SCALE / 2; + val = val * data->output_scale - data->output_scale / 2; - return val * DIV_ROUND_CLOSEST(vdd, - (1 << MCP3021_OUTPUT_RES) * MCP3021_OUTPUT_SCALE); + return val * DIV_ROUND_CLOSEST(data->vdd, + (1 << data->output_res) * data->output_scale); } static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, @@ -88,7 +104,8 @@ static ssize_t show_in_input(struct device *dev, struct device_attribute *attr, if (reg < 0) return reg; - in_input = volts_from_reg(data->vdd, reg); + in_input = volts_from_reg(data, reg); + return sprintf(buf, "%d\n", in_input); } @@ -103,25 +120,39 @@ static int mcp3021_probe(struct i2c_client *client, if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) return -ENODEV; - data = kzalloc(sizeof(struct mcp3021_data), GFP_KERNEL); + data = devm_kzalloc(&client->dev, sizeof(struct mcp3021_data), + GFP_KERNEL); if (!data) return -ENOMEM; i2c_set_clientdata(client, data); + switch (id->driver_data) { + case mcp3021: + data->sar_shift = MCP3021_SAR_SHIFT; + data->sar_mask = MCP3021_SAR_MASK; + data->output_res = MCP3021_OUTPUT_RES; + data->output_scale = MCP3021_OUTPUT_SCALE; + break; + + case mcp3221: + data->sar_shift = MCP3221_SAR_SHIFT; + data->sar_mask = MCP3221_SAR_MASK; + data->output_res = MCP3221_OUTPUT_RES; + data->output_scale = MCP3221_OUTPUT_SCALE; + break; + } + if (client->dev.platform_data) { data->vdd = *(u32 *)client->dev.platform_data; - if (data->vdd > MCP3021_VDD_MAX || - data->vdd < MCP3021_VDD_MIN) { - err = -EINVAL; - goto exit_free; - } + if (data->vdd > MCP3021_VDD_MAX || data->vdd < MCP3021_VDD_MIN) + return -EINVAL; } else data->vdd = MCP3021_VDD_REF; err = sysfs_create_file(&client->dev.kobj, &dev_attr_in0_input.attr); if (err) - goto exit_free; + return err; data->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(data->hwmon_dev)) { @@ -133,8 +164,6 @@ static int mcp3021_probe(struct i2c_client *client, exit_remove: sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr); -exit_free: - kfree(data); return err; } @@ -144,13 +173,13 @@ static int mcp3021_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_file(&client->dev.kobj, &dev_attr_in0_input.attr); - kfree(data); return 0; } static const struct i2c_device_id mcp3021_id[] = { - { "mcp3021", 0 }, + { "mcp3021", mcp3021 }, + { "mcp3221", mcp3221 }, { } }; MODULE_DEVICE_TABLE(i2c, mcp3021_id); @@ -167,5 +196,5 @@ static struct i2c_driver mcp3021_driver = { module_i2c_driver(mcp3021_driver); MODULE_AUTHOR("Mingkai Hu <Mingkai.hu@freescale.com>"); -MODULE_DESCRIPTION("Microchip MCP3021 driver"); +MODULE_DESCRIPTION("Microchip MCP3021/MCP3221 driver"); MODULE_LICENSE("GPL"); diff --git a/drivers/hwmon/sch5627.c b/drivers/hwmon/sch5627.c index 8342275378b..49f6230bdcf 100644 --- a/drivers/hwmon/sch5627.c +++ b/drivers/hwmon/sch5627.c @@ -461,8 +461,6 @@ static int sch5627_remove(struct platform_device *pdev) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&pdev->dev.kobj, &sch5627_group); - platform_set_drvdata(pdev, NULL); - kfree(data); return 0; } @@ -472,7 +470,8 @@ static int __devinit sch5627_probe(struct platform_device *pdev) struct sch5627_data *data; int err, build_code, build_id, hwmon_rev, val; - data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct sch5627_data), + GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/hwmon/sch5636.c b/drivers/hwmon/sch5636.c index 96a7e68718c..51711801619 100644 --- a/drivers/hwmon/sch5636.c +++ b/drivers/hwmon/sch5636.c @@ -402,9 +402,6 @@ static int sch5636_remove(struct platform_device *pdev) device_remove_file(&pdev->dev, &sch5636_fan_attr[i].dev_attr); - platform_set_drvdata(pdev, NULL); - kfree(data); - return 0; } @@ -414,7 +411,8 @@ static int __devinit sch5636_probe(struct platform_device *pdev) int i, err, val, revision[2]; char id[4]; - data = kzalloc(sizeof(struct sch5636_data), GFP_KERNEL); + data = devm_kzalloc(&pdev->dev, sizeof(struct sch5636_data), + GFP_KERNEL); if (!data) return -ENOMEM; diff --git a/drivers/hwmon/sch56xx-common.c b/drivers/hwmon/sch56xx-common.c index 4380f5d07be..d00b30adc34 100644 --- a/drivers/hwmon/sch56xx-common.c +++ b/drivers/hwmon/sch56xx-common.c @@ -503,10 +503,10 @@ EXPORT_SYMBOL(sch56xx_watchdog_unregister); * platform dev find, add and remove functions */ -static int __init sch56xx_find(int sioaddr, unsigned short *address, - const char **name) +static int __init sch56xx_find(int sioaddr, const char **name) { u8 devid; + unsigned short address; int err; err = superio_enter(sioaddr); @@ -540,20 +540,21 @@ static int __init sch56xx_find(int sioaddr, unsigned short *address, * Warning the order of the low / high byte is the other way around * as on most other superio devices!! */ - *address = superio_inb(sioaddr, SIO_REG_ADDR) | + address = superio_inb(sioaddr, SIO_REG_ADDR) | superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8; - if (*address == 0) { + if (address == 0) { pr_warn("Base address not set\n"); err = -ENODEV; goto exit; } + err = address; exit: superio_exit(sioaddr); return err; } -static int __init sch56xx_device_add(unsigned short address, const char *name) +static int __init sch56xx_device_add(int address, const char *name) { struct resource res = { .start = address, @@ -593,15 +594,14 @@ exit_device_put: static int __init sch56xx_init(void) { - int err; - unsigned short address; - const char *name; - - err = sch56xx_find(0x4e, &address, &name); - if (err) - err = sch56xx_find(0x2e, &address, &name); - if (err) - return err; + int address; + const char *name = NULL; + + address = sch56xx_find(0x4e, &name); + if (address < 0) + address = sch56xx_find(0x2e, &name); + if (address < 0) + return address; return sch56xx_device_add(address, name); } diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index 8b011d01662..07a0c1a0b84 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c @@ -1,7 +1,7 @@ /* * sht15.c - support for the SHT15 Temperature and Humidity Sensor * - * Portions Copyright (c) 2010-2011 Savoir-faire Linux Inc. + * Portions Copyright (c) 2010-2012 Savoir-faire Linux Inc. * Jerome Oufella <jerome.oufella@savoirfairelinux.com> * Vivien Didelot <vivien.didelot@savoirfairelinux.com> * @@ -24,12 +24,12 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> #include <linux/mutex.h> +#include <linux/platform_data/sht15.h> #include <linux/platform_device.h> #include <linux/sched.h> #include <linux/delay.h> #include <linux/jiffies.h> #include <linux/err.h> -#include <linux/sht15.h> #include <linux/regulator/consumer.h> #include <linux/slab.h> #include <linux/atomic.h> @@ -53,6 +53,9 @@ #define SHT15_STATUS_HEATER 0x04 #define SHT15_STATUS_LOW_BATTERY 0x40 +/* List of supported chips */ +enum sht15_chips { sht10, sht11, sht15, sht71, sht75 }; + /* Actions the driver may be doing */ enum sht15_state { SHT15_READING_NOTHING, @@ -884,14 +887,12 @@ static int sht15_invalidate_voltage(struct notifier_block *nb, static int __devinit sht15_probe(struct platform_device *pdev) { int ret; - struct sht15_data *data = kzalloc(sizeof(*data), GFP_KERNEL); + struct sht15_data *data; u8 status = 0; - if (!data) { - ret = -ENOMEM; - dev_err(&pdev->dev, "kzalloc failed\n"); - goto error_ret; - } + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; INIT_WORK(&data->read_work, sht15_bh_read_data); INIT_WORK(&data->update_supply_work, sht15_update_voltage); @@ -901,9 +902,8 @@ static int __devinit sht15_probe(struct platform_device *pdev) init_waitqueue_head(&data->wait_queue); if (pdev->dev.platform_data == NULL) { - ret = -EINVAL; dev_err(&pdev->dev, "no platform data supplied\n"); - goto err_free_data; + return -EINVAL; } data->pdata = pdev->dev.platform_data; data->supply_uV = data->pdata->supply_mv * 1000; @@ -918,7 +918,7 @@ static int __devinit sht15_probe(struct platform_device *pdev) * If a regulator is available, * query what the supply voltage actually is! */ - data->reg = regulator_get(data->dev, "vcc"); + data->reg = devm_regulator_get(data->dev, "vcc"); if (!IS_ERR(data->reg)) { int voltage; @@ -937,51 +937,51 @@ static int __devinit sht15_probe(struct platform_device *pdev) dev_err(&pdev->dev, "regulator notifier request failed\n"); regulator_disable(data->reg); - regulator_put(data->reg); - goto err_free_data; + return ret; } } /* Try requesting the GPIOs */ - ret = gpio_request(data->pdata->gpio_sck, "SHT15 sck"); + ret = devm_gpio_request(&pdev->dev, data->pdata->gpio_sck, "SHT15 sck"); if (ret) { dev_err(&pdev->dev, "gpio request failed\n"); goto err_release_reg; } gpio_direction_output(data->pdata->gpio_sck, 0); - ret = gpio_request(data->pdata->gpio_data, "SHT15 data"); + ret = devm_gpio_request(&pdev->dev, data->pdata->gpio_data, + "SHT15 data"); if (ret) { dev_err(&pdev->dev, "gpio request failed\n"); - goto err_release_gpio_sck; + goto err_release_reg; } - ret = request_irq(gpio_to_irq(data->pdata->gpio_data), - sht15_interrupt_fired, - IRQF_TRIGGER_FALLING, - "sht15 data", - data); + ret = devm_request_irq(&pdev->dev, gpio_to_irq(data->pdata->gpio_data), + sht15_interrupt_fired, + IRQF_TRIGGER_FALLING, + "sht15 data", + data); if (ret) { dev_err(&pdev->dev, "failed to get irq for data line\n"); - goto err_release_gpio_data; + goto err_release_reg; } disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data)); sht15_connection_reset(data); ret = sht15_soft_reset(data); if (ret) - goto err_release_irq; + goto err_release_reg; /* write status with platform data options */ if (status) { ret = sht15_send_status(data, status); if (ret) - goto err_release_irq; + goto err_release_reg; } ret = sysfs_create_group(&pdev->dev.kobj, &sht15_attr_group); if (ret) { dev_err(&pdev->dev, "sysfs create failed\n"); - goto err_release_irq; + goto err_release_reg; } data->hwmon_dev = hwmon_device_register(data->dev); @@ -994,21 +994,11 @@ static int __devinit sht15_probe(struct platform_device *pdev) err_release_sysfs_group: sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group); -err_release_irq: - free_irq(gpio_to_irq(data->pdata->gpio_data), data); -err_release_gpio_data: - gpio_free(data->pdata->gpio_data); -err_release_gpio_sck: - gpio_free(data->pdata->gpio_sck); err_release_reg: if (!IS_ERR(data->reg)) { regulator_unregister_notifier(data->reg, &data->nb); regulator_disable(data->reg); - regulator_put(data->reg); } -err_free_data: - kfree(data); -error_ret: return ret; } @@ -1030,89 +1020,33 @@ static int __devexit sht15_remove(struct platform_device *pdev) if (!IS_ERR(data->reg)) { regulator_unregister_notifier(data->reg, &data->nb); regulator_disable(data->reg); - regulator_put(data->reg); } - free_irq(gpio_to_irq(data->pdata->gpio_data), data); - gpio_free(data->pdata->gpio_data); - gpio_free(data->pdata->gpio_sck); mutex_unlock(&data->read_lock); - kfree(data); return 0; } -/* - * sht_drivers simultaneously refers to __devinit and __devexit function - * which causes spurious section mismatch warning. So use __refdata to - * get rid from this. - */ -static struct platform_driver __refdata sht_drivers[] = { - { - .driver = { - .name = "sht10", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht11", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht15", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht71", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, { - .driver = { - .name = "sht75", - .owner = THIS_MODULE, - }, - .probe = sht15_probe, - .remove = __devexit_p(sht15_remove), - }, +static struct platform_device_id sht15_device_ids[] = { + { "sht10", sht10 }, + { "sht11", sht11 }, + { "sht15", sht15 }, + { "sht71", sht71 }, + { "sht75", sht75 }, + { } }; +MODULE_DEVICE_TABLE(platform, sht15_device_ids); -static int __init sht15_init(void) -{ - int ret; - int i; - - for (i = 0; i < ARRAY_SIZE(sht_drivers); i++) { - ret = platform_driver_register(&sht_drivers[i]); - if (ret) - goto error_unreg; - } - - return 0; - -error_unreg: - while (--i >= 0) - platform_driver_unregister(&sht_drivers[i]); - - return ret; -} -module_init(sht15_init); - -static void __exit sht15_exit(void) -{ - int i; - for (i = ARRAY_SIZE(sht_drivers) - 1; i >= 0; i--) - platform_driver_unregister(&sht_drivers[i]); -} -module_exit(sht15_exit); +static struct platform_driver sht15_driver = { + .driver = { + .name = "sht15", + .owner = THIS_MODULE, + }, + .probe = sht15_probe, + .remove = __devexit_p(sht15_remove), + .id_table = sht15_device_ids, +}; +module_platform_driver(sht15_driver); MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Sensirion SHT15 temperature and humidity sensor driver"); diff --git a/drivers/hwmon/sht21.c b/drivers/hwmon/sht21.c index 6c2dede4b8e..c2565d04cd4 100644 --- a/drivers/hwmon/sht21.c +++ b/drivers/hwmon/sht21.c @@ -199,11 +199,10 @@ static int __devinit sht21_probe(struct i2c_client *client, return -ENODEV; } - sht21 = kzalloc(sizeof(*sht21), GFP_KERNEL); - if (!sht21) { - dev_dbg(&client->dev, "kzalloc failed\n"); + sht21 = devm_kzalloc(&client->dev, sizeof(*sht21), GFP_KERNEL); + if (!sht21) return -ENOMEM; - } + i2c_set_clientdata(client, sht21); mutex_init(&sht21->lock); @@ -211,7 +210,7 @@ static int __devinit sht21_probe(struct i2c_client *client, err = sysfs_create_group(&client->dev.kobj, &sht21_attr_group); if (err) { dev_dbg(&client->dev, "could not create sysfs files\n"); - goto fail_free; + return err; } sht21->hwmon_dev = hwmon_device_register(&client->dev); if (IS_ERR(sht21->hwmon_dev)) { @@ -226,9 +225,6 @@ static int __devinit sht21_probe(struct i2c_client *client, fail_remove_sysfs: sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); -fail_free: - kfree(sht21); - return err; } @@ -242,7 +238,6 @@ static int __devexit sht21_remove(struct i2c_client *client) hwmon_device_unregister(sht21->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &sht21_attr_group); - kfree(sht21); return 0; } diff --git a/drivers/hwmon/via-cputemp.c b/drivers/hwmon/via-cputemp.c index 2e56c6ce9fb..4cddee04f2e 100644 --- a/drivers/hwmon/via-cputemp.c +++ b/drivers/hwmon/via-cputemp.c @@ -128,12 +128,10 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) int err; u32 eax, edx; - data = kzalloc(sizeof(struct via_cputemp_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - dev_err(&pdev->dev, "Out of memory\n"); - goto exit; - } + data = devm_kzalloc(&pdev->dev, sizeof(struct via_cputemp_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; data->id = pdev->id; data->name = "via_cputemp"; @@ -151,8 +149,7 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) data->msr_temp = 0x1423; break; default: - err = -ENODEV; - goto exit_free; + return -ENODEV; } /* test if we can access the TEMPERATURE MSR */ @@ -160,14 +157,14 @@ static int __devinit via_cputemp_probe(struct platform_device *pdev) if (err) { dev_err(&pdev->dev, "Unable to access TEMPERATURE MSR, giving up\n"); - goto exit_free; + return err; } platform_set_drvdata(pdev, data); err = sysfs_create_group(&pdev->dev.kobj, &via_cputemp_group); if (err) - goto exit_free; + return err; if (data->msr_vid) data->vrm = vid_which_vrm(); @@ -192,10 +189,6 @@ exit_remove: if (data->vrm) device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); -exit_free: - platform_set_drvdata(pdev, NULL); - kfree(data); -exit: return err; } @@ -207,8 +200,6 @@ static int __devexit via_cputemp_remove(struct platform_device *pdev) if (data->vrm) device_remove_file(&pdev->dev, &dev_attr_cpu0_vid); sysfs_remove_group(&pdev->dev.kobj, &via_cputemp_group); - platform_set_drvdata(pdev, NULL); - kfree(data); return 0; } diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c index 386a8453801..84e3dc5e3a8 100644 --- a/drivers/hwmon/vt8231.c +++ b/drivers/hwmon/vt8231.c @@ -789,18 +789,16 @@ static int vt8231_probe(struct platform_device *pdev) /* Reserve the ISA region */ res = platform_get_resource(pdev, IORESOURCE_IO, 0); - if (!request_region(res->start, VT8231_EXTENT, - vt8231_driver.driver.name)) { + if (!devm_request_region(&pdev->dev, res->start, VT8231_EXTENT, + vt8231_driver.driver.name)) { dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n", (unsigned long)res->start, (unsigned long)res->end); return -ENODEV; } - data = kzalloc(sizeof(struct vt8231_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit_release; - } + data = devm_kzalloc(&pdev->dev, sizeof(struct vt8231_data), GFP_KERNEL); + if (!data) + return -ENOMEM; platform_set_drvdata(pdev, data); data->addr = res->start; @@ -812,7 +810,7 @@ static int vt8231_probe(struct platform_device *pdev) /* Register sysfs hooks */ err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group); if (err) - goto exit_free; + return err; /* Must update device information to find out the config field */ data->uch_config = vt8231_read_value(data, VT8231_REG_UCH_CONFIG); @@ -850,13 +848,6 @@ exit_remove_files: sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]); sysfs_remove_group(&pdev->dev.kobj, &vt8231_group); - -exit_free: - platform_set_drvdata(pdev, NULL); - kfree(data); - -exit_release: - release_region(res->start, VT8231_EXTENT); return err; } @@ -875,9 +866,6 @@ static int __devexit vt8231_remove(struct platform_device *pdev) sysfs_remove_group(&pdev->dev.kobj, &vt8231_group); - release_region(data->addr, VT8231_EXTENT); - platform_set_drvdata(pdev, NULL); - kfree(data); return 0; } diff --git a/drivers/hwmon/w83791d.c b/drivers/hwmon/w83791d.c index 9ade4d4e218..93ea81a4bf3 100644 --- a/drivers/hwmon/w83791d.c +++ b/drivers/hwmon/w83791d.c @@ -259,8 +259,7 @@ static u8 fan_to_reg(long rpm, int div) ((val) + 500) / 1000) /* for thermal cruise temp tolerance, 4-bits, LSB = 1 degree Celsius */ -#define TOL_TEMP_TO_REG(val) ((val) < 0 ? 0 : \ - (val) >= 15000 ? 15 : \ +#define TOL_TEMP_TO_REG(val) ((val) >= 15000 ? 15 : \ ((val) + 500) / 1000) #define BEEP_MASK_TO_REG(val) ((val) & 0xffffff) @@ -848,10 +847,10 @@ static ssize_t store_temp_target(struct device *dev, struct i2c_client *client = to_i2c_client(dev); struct w83791d_data *data = i2c_get_clientdata(client); int nr = sensor_attr->index; - unsigned long val; + long val; u8 target_mask; - if (kstrtoul(buf, 10, &val)) + if (kstrtol(buf, 10, &val)) return -EINVAL; mutex_lock(&data->update_lock); diff --git a/drivers/hwmon/w83792d.c b/drivers/hwmon/w83792d.c index 0ba5a2bd562..06d6f56d4f6 100644 --- a/drivers/hwmon/w83792d.c +++ b/drivers/hwmon/w83792d.c @@ -296,7 +296,6 @@ struct w83792d_data { u8 pwmenable[3]; u32 alarms; /* realtime status register encoding,combined */ u8 chassis; /* Chassis status */ - u8 chassis_clear; /* CLR_CHS, clear chassis intrusion detection */ u8 thermal_cruise[3]; /* Smart FanI: Fan1,2,3 target value */ u8 tolerance[3]; /* Fan1,2,3 tolerance(Smart Fan I/II) */ u8 sf2_points[3][4]; /* Smart FanII: Fan1,2,3 temperature points */ @@ -739,7 +738,7 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr, } static ssize_t -show_chassis(struct device *dev, struct device_attribute *attr, +show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) { struct w83792d_data *data = w83792d_update_device(dev); @@ -747,52 +746,6 @@ show_chassis(struct device *dev, struct device_attribute *attr, } static ssize_t -show_regs_chassis(struct device *dev, struct device_attribute *attr, - char *buf) -{ - dev_warn(dev, - "Attribute %s is deprecated, use intrusion0_alarm instead\n", - "chassis"); - return show_chassis(dev, attr, buf); -} - -static ssize_t -show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct w83792d_data *data = w83792d_update_device(dev); - return sprintf(buf, "%d\n", data->chassis_clear); -} - -static ssize_t -store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83792d_data *data = i2c_get_clientdata(client); - unsigned long val; - int err; - u8 temp1 = 0, temp2 = 0; - - dev_warn(dev, - "Attribute %s is deprecated, use intrusion0_alarm instead\n", - "chassis_clear"); - - err = kstrtoul(buf, 10, &val); - if (err) - return err; - - mutex_lock(&data->update_lock); - data->chassis_clear = SENSORS_LIMIT(val, 0, 1); - temp1 = ((data->chassis_clear) << 7) & 0x80; - temp2 = w83792d_read_value(client, - W83792D_REG_CHASSIS_CLR) & 0x7f; - w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2); - mutex_unlock(&data->update_lock); - - return count; -} - -static ssize_t store_chassis_clear(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { @@ -1116,11 +1069,8 @@ static SENSOR_DEVICE_ATTR(in8_alarm, S_IRUGO, show_alarm, NULL, 20); static SENSOR_DEVICE_ATTR(fan4_alarm, S_IRUGO, show_alarm, NULL, 21); static SENSOR_DEVICE_ATTR(fan5_alarm, S_IRUGO, show_alarm, NULL, 22); static SENSOR_DEVICE_ATTR(fan6_alarm, S_IRUGO, show_alarm, NULL, 23); -static DEVICE_ATTR(chassis, S_IRUGO, show_regs_chassis, NULL); -static DEVICE_ATTR(chassis_clear, S_IRUGO | S_IWUSR, - show_chassis_clear, store_chassis_clear_legacy); static DEVICE_ATTR(intrusion0_alarm, S_IRUGO | S_IWUSR, - show_chassis, store_chassis_clear); + show_chassis_clear, store_chassis_clear); static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0); static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1); static SENSOR_DEVICE_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 2); @@ -1320,8 +1270,6 @@ static struct attribute *w83792d_attributes[] = { &sensor_dev_attr_pwm3_mode.dev_attr.attr, &sensor_dev_attr_pwm3_enable.dev_attr.attr, &dev_attr_alarms.attr, - &dev_attr_chassis.attr, - &dev_attr_chassis_clear.attr, &dev_attr_intrusion0_alarm.attr, &sensor_dev_attr_tolerance1.dev_attr.attr, &sensor_dev_attr_thermal_cruise1.dev_attr.attr, @@ -1627,8 +1575,6 @@ static struct w83792d_data *w83792d_update_device(struct device *dev) /* Update CaseOpen status and it's CLR_CHS. */ data->chassis = (w83792d_read_value(client, W83792D_REG_CHASSIS) >> 5) & 0x01; - data->chassis_clear = (w83792d_read_value(client, - W83792D_REG_CHASSIS_CLR) >> 7) & 0x01; /* Update Thermal Cruise/Smart Fan I target value */ for (i = 0; i < 3; i++) { diff --git a/drivers/hwmon/w83793.c b/drivers/hwmon/w83793.c index d6b0bdd4865..4fc47e06207 100644 --- a/drivers/hwmon/w83793.c +++ b/drivers/hwmon/w83793.c @@ -442,27 +442,6 @@ store_beep_enable(struct device *dev, struct device_attribute *attr, return count; } -/* Write any value to clear chassis alarm */ -static ssize_t -store_chassis_clear_legacy(struct device *dev, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct i2c_client *client = to_i2c_client(dev); - struct w83793_data *data = i2c_get_clientdata(client); - u8 val; - - dev_warn(dev, "Attribute chassis is deprecated, " - "use intrusion0_alarm instead\n"); - - mutex_lock(&data->update_lock); - val = w83793_read_value(client, W83793_REG_CLR_CHASSIS); - val |= 0x80; - w83793_write_value(client, W83793_REG_CLR_CHASSIS, val); - mutex_unlock(&data->update_lock); - return count; -} - /* Write 0 to clear chassis alarm */ static ssize_t store_chassis_clear(struct device *dev, @@ -1189,8 +1168,6 @@ static struct sensor_device_attribute_2 w83793_vid[] = { static DEVICE_ATTR(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm); static struct sensor_device_attribute_2 sda_single_files[] = { - SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep, - store_chassis_clear_legacy, ALARM_STATUS, 30), SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep, store_chassis_clear, ALARM_STATUS, 30), SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_beep_enable, diff --git a/drivers/hwmon/w83l786ng.c b/drivers/hwmon/w83l786ng.c index 5850b770608..c99c8a0473c 100644 --- a/drivers/hwmon/w83l786ng.c +++ b/drivers/hwmon/w83l786ng.c @@ -668,11 +668,10 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) int i, err = 0; u8 reg_tmp; - data = kzalloc(sizeof(struct w83l786ng_data), GFP_KERNEL); - if (!data) { - err = -ENOMEM; - goto exit; - } + data = devm_kzalloc(&client->dev, sizeof(struct w83l786ng_data), + GFP_KERNEL); + if (!data) + return -ENOMEM; i2c_set_clientdata(client, data); mutex_init(&data->update_lock); @@ -708,8 +707,6 @@ w83l786ng_probe(struct i2c_client *client, const struct i2c_device_id *id) exit_remove: sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); - kfree(data); -exit: return err; } @@ -721,8 +718,6 @@ w83l786ng_remove(struct i2c_client *client) hwmon_device_unregister(data->hwmon_dev); sysfs_remove_group(&client->dev.kobj, &w83l786ng_group); - kfree(data); - return 0; } diff --git a/include/linux/platform_data/max197.h b/include/linux/platform_data/max197.h new file mode 100644 index 00000000000..e2a41dd7690 --- /dev/null +++ b/include/linux/platform_data/max197.h @@ -0,0 +1,21 @@ +/* + * Maxim MAX197 A/D Converter Driver + * + * Copyright (c) 2012 Savoir-faire Linux Inc. + * Vivien Didelot <vivien.didelot@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * For further information, see the Documentation/hwmon/max197 file. + */ + +/** + * struct max197_platform_data - MAX197 connectivity info + * @convert: Function used to start a conversion with control byte ctrl. + * It must return the raw data, or a negative error code. + */ +struct max197_platform_data { + int (*convert)(u8 ctrl); +}; diff --git a/include/linux/sht15.h b/include/linux/platform_data/sht15.h index f85c7c523da..33e0fd27225 100644 --- a/include/linux/sht15.h +++ b/include/linux/platform_data/sht15.h @@ -31,4 +31,3 @@ struct sht15_platform_data { bool no_otp_reload; bool low_resolution; }; - |