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
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1.4.11 (GNU/Linux)
 
 iQIcBAABAgAGBQJQafNMAAoJEMsfJm/On5mB44AP+gOihuehPqkX2n22sPpnIZfa
 xATGTK0ju3kDlEIAM6p1fnw42+RXXseOVXy3GybvvzyqV8gAC4pWVCTshjOcXRAO
 MBgLF9z2UZjhJQzlkWfKPOAHfN94ALTb5SpN2iv94Ecm6vfG6Le4FzhTszjryeb5
 nib1jmEjhajHtGy7Ezc1+o1VZhXdJSGi+N1AjL+ysDMeAOf69c1tg/9P5tp/Rw3G
 jHbtozG6oj9IWbZIhiGpWnJ4fA740+eKLfNwssb0bfpSNa0MlBGm6DlYB+hnQ/8V
 dyV7r67zFMkDjYMPbeA+XiZxmPTPaNZ/E54lzOSaSU28F9uaACkNdc/3QJGPClgJ
 nmFdWiMGSkMYn9QdbYWrGkxr6Dd0ezPDIcqqvrfL4V/iKWyhshPjEEMKEsQZenjw
 0gveTfmGt5LWHAj6WKB0o0mjTtCSrohTIKzK5udrVhv1I7kdeoQ3/Q//yI5+saum
 MPP2DSJlZME80IkFX6iSvMy5TwSmaqd++DfFxJZgo1qiex4P/X5jYhAV4oboqGm4
 Lz0BoPTvtY1CQK9mKsiJObHzFmzMou9HSC965RfzpcP3VWKuVMo4UuN45BJ0pBtK
 m7Zpmjx6FqWjxXGCR96FU11S8LgSFegcF8q3UxQCphARt7aSPbD3NRsArYP0Zgfb
 bWxJjPiJSFlMiTcMrTl+
 =ucH8
 -----END PGP SIGNATURE-----

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
  ...
This commit is contained in:
Linus Torvalds 2012-10-01 13:50:06 -07:00
commit cc150a2861
61 changed files with 1527 additions and 881 deletions

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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
---------

View File

@ -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

View File

@ -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).

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

464
drivers/hwmon/adt7410.c Normal file
View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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) = {

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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");

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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, &ltc4151_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, &ltc4151_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, &ltc4151_group);
kfree(data);
return 0;
}

View File

@ -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, &ltc4215_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, &ltc4215_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, &ltc4215_group);
kfree(data);
return 0;
}

View File

@ -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;
}

View File

@ -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");

View File

@ -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;
}

349
drivers/hwmon/max197.c Normal file
View File

@ -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");

View File

@ -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");

View File

@ -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;

View File

@ -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;

View File

@ -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;
int address;
const char *name = NULL;
err = sch56xx_find(0x4e, &address, &name);
if (err)
err = sch56xx_find(0x2e, &address, &name);
if (err)
return err;
address = sch56xx_find(0x4e, &name);
if (address < 0)
address = sch56xx_find(0x2e, &name);
if (address < 0)
return address;
return sch56xx_device_add(address, name);
}

View File

@ -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");

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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);

View File

@ -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,59 +738,13 @@ 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);
return sprintf(buf, "%d\n", data->chassis);
}
static ssize_t
show_regs_chassis(struct device *dev, struct device_attribute *attr,
char *buf)
{
dev_warn(dev,
"Attribute %s is deprecated, use intrusion0_alarm instead\n",
"chassis");
return show_chassis(dev, attr, buf);
}
static ssize_t
show_chassis_clear(struct device *dev, struct device_attribute *attr, char *buf)
{
struct w83792d_data *data = w83792d_update_device(dev);
return sprintf(buf, "%d\n", data->chassis_clear);
}
static ssize_t
store_chassis_clear_legacy(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct i2c_client *client = to_i2c_client(dev);
struct w83792d_data *data = i2c_get_clientdata(client);
unsigned long val;
int err;
u8 temp1 = 0, temp2 = 0;
dev_warn(dev,
"Attribute %s is deprecated, use intrusion0_alarm instead\n",
"chassis_clear");
err = kstrtoul(buf, 10, &val);
if (err)
return err;
mutex_lock(&data->update_lock);
data->chassis_clear = SENSORS_LIMIT(val, 0, 1);
temp1 = ((data->chassis_clear) << 7) & 0x80;
temp2 = w83792d_read_value(client,
W83792D_REG_CHASSIS_CLR) & 0x7f;
w83792d_write_value(client, W83792D_REG_CHASSIS_CLR, temp1 | temp2);
mutex_unlock(&data->update_lock);
return count;
}
static ssize_t
store_chassis_clear(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
@ -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++) {

View File

@ -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,

View File

@ -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;
}

View File

@ -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);
};

View File

@ -31,4 +31,3 @@ struct sht15_platform_data {
bool no_otp_reload;
bool low_resolution;
};