mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-15 08:44:14 +08:00
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:
commit
cc150a2861
@ -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
|
||||
|
51
Documentation/hwmon/adt7410
Normal file
51
Documentation/hwmon/adt7410
Normal 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
|
@ -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.
|
||||
|
@ -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
|
||||
---------
|
||||
|
60
Documentation/hwmon/max197
Normal file
60
Documentation/hwmon/max197
Normal 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
|
@ -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).
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
464
drivers/hwmon/adt7410.c
Normal 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");
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) = {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -181,11 +181,9 @@ static int ltc4151_probe(struct i2c_client *client,
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
ret = -ENOMEM;
|
||||
goto out_kzalloc;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@ -193,7 +191,7 @@ static int ltc4151_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
ret = sysfs_create_group(&client->dev.kobj, <c4151_group);
|
||||
if (ret)
|
||||
goto out_sysfs_create_group;
|
||||
return ret;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
@ -205,9 +203,6 @@ static int ltc4151_probe(struct i2c_client *client,
|
||||
|
||||
out_hwmon_device_register:
|
||||
sysfs_remove_group(&client->dev.kobj, <c4151_group);
|
||||
out_sysfs_create_group:
|
||||
kfree(data);
|
||||
out_kzalloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -218,8 +213,6 @@ static int ltc4151_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, <c4151_group);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -253,11 +253,9 @@ static int ltc4215_probe(struct i2c_client *client,
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
if (!data) {
|
||||
ret = -ENOMEM;
|
||||
goto out_kzalloc;
|
||||
}
|
||||
data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
|
||||
if (!data)
|
||||
return -ENOMEM;
|
||||
|
||||
i2c_set_clientdata(client, data);
|
||||
mutex_init(&data->update_lock);
|
||||
@ -268,7 +266,7 @@ static int ltc4215_probe(struct i2c_client *client,
|
||||
/* Register sysfs hooks */
|
||||
ret = sysfs_create_group(&client->dev.kobj, <c4215_group);
|
||||
if (ret)
|
||||
goto out_sysfs_create_group;
|
||||
return ret;
|
||||
|
||||
data->hwmon_dev = hwmon_device_register(&client->dev);
|
||||
if (IS_ERR(data->hwmon_dev)) {
|
||||
@ -280,9 +278,6 @@ static int ltc4215_probe(struct i2c_client *client,
|
||||
|
||||
out_hwmon_device_register:
|
||||
sysfs_remove_group(&client->dev.kobj, <c4215_group);
|
||||
out_sysfs_create_group:
|
||||
kfree(data);
|
||||
out_kzalloc:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -293,8 +288,6 @@ static int ltc4215_remove(struct i2c_client *client)
|
||||
hwmon_device_unregister(data->hwmon_dev);
|
||||
sysfs_remove_group(&client->dev.kobj, <c4215_group);
|
||||
|
||||
kfree(data);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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
349
drivers/hwmon/max197.c
Normal 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");
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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++) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
21
include/linux/platform_data/max197.h
Normal file
21
include/linux/platform_data/max197.h
Normal 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);
|
||||
};
|
@ -31,4 +31,3 @@ struct sht15_platform_data {
|
||||
bool no_otp_reload;
|
||||
bool low_resolution;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user