Commit f4562052 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'hwmon-for-linus' of...

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

Pull hwmon updates from Guenter Roeck:
 "New driver for NCT6683D

  New chip support to existing drivers:
   - add support for STTS2004 and AT30TSE004 to jc42 driver
   - add support for EMC1402/EMC1412/EMC1422 to emc1403 driver

  Other notable changes:
   - document hwmon kernel API
   - convert jc42, lm70, lm75, lm77, lm83, lm92, max1619, tmp421, and
     tmp102 drivers to use new hwmon API functions
   - replace function macros in lm80, lm92, and jc42 drivers with real
     code
   - convert emc1403 driver to use regmap, add support for additional
     attributes, and add device IDs for EMC1412, EMC1413, and EMC1414
   - various additional cleanup and minor bug fixes in several drivers"

* tag 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (60 commits)
  hwmon: (nct6775) Fix probe unwind paths to properly unregister platform devices
  hwmon: (nct6683) Fix probe unwind paths to properly unregister platform devices
  hwmon: (ultra45_env) Introduce managed version of kzalloc
  hwmon: Driver for NCT6683D
  hwmon: (lm80) Rearrange code to avoid forward declarations
  hwmon: (lm80) Convert fan display function macros into functions
  hwmon: (lm80) Convert voltage display function macros into functions
  hwmon: (lm80) Convert temperature display function macros into functions
  hwmon: (lm80) Normalize all temperature values to 16 bit
  hwmon: (lm80) Simplify TEMP_FROM_REG
  hwmon: (lm83) Convert to use devm_hwmon_device_register_with_groups
  hwmon: (lm83) Rearange code to avoid forward declarations
  hwmon: (lm83) Drop FSF address
  hwmon: (max1619) Convert to use devm_hwmon_device_register_with_groups
  hwmon: (max1619) Drop function macros
  hwmon: (max1619) Rearrange code to avoid forward declarations
  hwmon: (max1619) Drop FSF address
  hwmon: (max1619) Fix critical alarm display
  hwmon: (jc42) Add support for STTS2004 and AT30TSE004
  hwmon: (jc42) Convert function macros into functions
  ...
parents 8f5759ae 9d311edd
Kernel driver emc1403
=====================
Supported chips:
* SMSC / Microchip EMC1402, EMC1412
Addresses scanned: I2C 0x18, 0x1c, 0x29, 0x4c, 0x4d, 0x5c
Prefix: 'emc1402'
Datasheets:
http://ww1.microchip.com/downloads/en/DeviceDoc/1412.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/1402.pdf
* SMSC / Microchip EMC1403, EMC1404, EMC1413, EMC1414
Addresses scanned: I2C 0x18, 0x29, 0x4c, 0x4d
Prefix: 'emc1403', 'emc1404'
Datasheets:
http://ww1.microchip.com/downloads/en/DeviceDoc/1403_1404.pdf
http://ww1.microchip.com/downloads/en/DeviceDoc/1413_1414.pdf
* SMSC / Microchip EMC1422
Addresses scanned: I2C 0x4c
Prefix: 'emc1422'
Datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/1422.pdf
* SMSC / Microchip EMC1423, EMC1424
Addresses scanned: I2C 0x4c
Prefix: 'emc1423', 'emc1424'
Datasheet:
http://ww1.microchip.com/downloads/en/DeviceDoc/1423_1424.pdf
Author:
Kalhan Trisal <kalhan.trisal@intel.com
Description
-----------
The Standard Microsystems Corporation (SMSC) / Microchip EMC14xx chips
contain up to four temperature sensors. EMC14x2 support two sensors
(one internal, one external). EMC14x3 support three sensors (one internal,
two external), and EMC14x4 support four sensors (one internal, three
external).
The chips implement three limits for each sensor: low (tempX_min), high
(tempX_max) and critical (tempX_crit.) The chips also implement an
hysteresis mechanism which applies to all limits. The relative difference
is stored in a single register on the chip, which means that the relative
difference between the limit and its hysteresis is always the same for
all three limits.
This implementation detail implies the following:
* When setting a limit, its hysteresis will automatically follow, the
difference staying unchanged. For example, if the old critical limit
was 80 degrees C, and the hysteresis was 75 degrees C, and you change
the critical limit to 90 degrees C, then the hysteresis will
automatically change to 85 degrees C.
* The hysteresis values can't be set independently. We decided to make
only temp1_crit_hyst writable, while all other hysteresis attributes
are read-only. Setting temp1_crit_hyst writes the difference between
temp1_crit_hyst and temp1_crit into the chip, and the same relative
hysteresis applies automatically to all other limits.
* The limits should be set before the hysteresis.
The Linux Hardware Monitoring kernel API.
=========================================
Guenter Roeck
Introduction
------------
This document describes the API that can be used by hardware monitoring
drivers that want to use the hardware monitoring framework.
This document does not describe what a hardware monitoring (hwmon) Driver or
Device is. It also does not describe the API which can be used by user space
to communicate with a hardware monitoring device. If you want to know this
then please read the following file: Documentation/hwmon/sysfs-interface.
For additional guidelines on how to write and improve hwmon drivers, please
also read Documentation/hwmon/submitting-patches.
The API
-------
Each hardware monitoring driver must #include <linux/hwmon.h> and, in most
cases, <linux/hwmon-sysfs.h>. linux/hwmon.h declares the following
register/unregister functions:
struct device *hwmon_device_register(struct device *dev);
struct device *
hwmon_device_register_with_groups(struct device *dev, const char *name,
void *drvdata,
const struct attribute_group **groups);
struct device *
devm_hwmon_device_register_with_groups(struct device *dev,
const char *name, void *drvdata,
const struct attribute_group **groups);
void hwmon_device_unregister(struct device *dev);
void devm_hwmon_device_unregister(struct device *dev);
hwmon_device_register registers a hardware monitoring device. The parameter
of this function is a pointer to the parent device.
This function returns a pointer to the newly created hardware monitoring device
or PTR_ERR for failure. If this registration function is used, hardware
monitoring sysfs attributes are expected to have been created and attached to
the parent device prior to calling hwmon_device_register. A name attribute must
have been created by the caller.
hwmon_device_register_with_groups is similar to hwmon_device_register. However,
it has additional parameters. The name parameter is a pointer to the hwmon
device name. The registration function wil create a name sysfs attribute
pointing to this name. The drvdata parameter is the pointer to the local
driver data. hwmon_device_register_with_groups will attach this pointer
to the newly allocated hwmon device. The pointer can be retrieved by the driver
using dev_get_drvdata() on the hwmon device pointer. The groups parameter is
a pointer to a list of sysfs attribute groups. The list must be NULL terminated.
hwmon_device_register_with_groups creates the hwmon device with name attribute
as well as all sysfs attributes attached to the hwmon device.
devm_hwmon_device_register_with_groups is similar to
hwmon_device_register_with_groups. However, it is device managed, meaning the
hwmon device does not have to be removed explicitly by the removal function.
hwmon_device_unregister deregisters a registered hardware monitoring device.
The parameter of this function is the pointer to the registered hardware
monitoring device structure. This function must be called from the driver
remove function if the hardware monitoring device was registered with
hwmon_device_register or with hwmon_device_register_with_groups.
devm_hwmon_device_unregister does not normally have to be called. It is only
needed for error handling, and only needed if the driver probe fails after
the call to devm_hwmon_device_register_with_groups.
The header file linux/hwmon-sysfs.h provides a number of useful macros to
declare and use hardware monitoring sysfs attributes.
In many cases, you can use the exsting define DEVICE_ATTR to declare such
attributes. This is feasible if an attribute has no additional context. However,
in many cases there will be additional information such as a sensor index which
will need to be passed to the sysfs attribute handling function.
SENSOR_DEVICE_ATTR and SENSOR_DEVICE_ATTR_2 can be used to define attributes
which need such additional context information. SENSOR_DEVICE_ATTR requires
one additional argument, SENSOR_DEVICE_ATTR_2 requires two.
SENSOR_DEVICE_ATTR defines a struct sensor_device_attribute variable.
This structure has the following fields.
struct sensor_device_attribute {
struct device_attribute dev_attr;
int index;
};
You can use to_sensor_dev_attr to get the pointer to this structure from the
attribute read or write function. Its parameter is the device to which the
attribute is attached.
SENSOR_DEVICE_ATTR_2 defines a struct sensor_device_attribute_2 variable,
which is defined as follows.
struct sensor_device_attribute_2 {
struct device_attribute dev_attr;
u8 index;
u8 nr;
};
Use to_sensor_dev_attr_2 to get the pointer to this structure. Its parameter
is the device to which the attribute is attached.
...@@ -5,9 +5,12 @@ Supported chips: ...@@ -5,9 +5,12 @@ Supported chips:
* Analog Devices ADT7408 * Analog Devices ADT7408
Datasheets: Datasheets:
http://www.analog.com/static/imported-files/data_sheets/ADT7408.pdf http://www.analog.com/static/imported-files/data_sheets/ADT7408.pdf
* Atmel AT30TS00 * Atmel AT30TS00, AT30TS002A/B, AT30TSE004A
Datasheets: Datasheets:
http://www.atmel.com/Images/doc8585.pdf http://www.atmel.com/Images/doc8585.pdf
http://www.atmel.com/Images/doc8711.pdf
http://www.atmel.com/Images/Atmel-8852-SEEPROM-AT30TSE002A-Datasheet.pdf
http://www.atmel.com/Images/Atmel-8868-DTS-AT30TSE004A-Datasheet.pdf
* IDT TSE2002B3, TSE2002GB2, TS3000B3, TS3000GB2 * IDT TSE2002B3, TSE2002GB2, TS3000B3, TS3000GB2
Datasheets: Datasheets:
http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf http://www.idt.com/sites/default/files/documents/IDT_TSE2002B3C_DST_20100512_120303152056.pdf
...@@ -34,12 +37,13 @@ Supported chips: ...@@ -34,12 +37,13 @@ Supported chips:
Datasheet: Datasheet:
http://www.onsemi.com/pub_link/Collateral/CAT34TS02-D.PDF http://www.onsemi.com/pub_link/Collateral/CAT34TS02-D.PDF
http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF http://www.onsemi.com/pub/Collateral/CAT6095-D.PDF
* ST Microelectronics STTS424, STTS424E02, STTS2002, STTS3000 * ST Microelectronics STTS424, STTS424E02, STTS2002, STTS2004, STTS3000
Datasheets: Datasheets:
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00157556.pdf http://www.st.com/web/en/resource/technical/document/datasheet/CD00157556.pdf
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00157558.pdf http://www.st.com/web/en/resource/technical/document/datasheet/CD00157558.pdf
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATASHEET/CD00225278.pdf http://www.st.com/web/en/resource/technical/document/datasheet/CD00266638.pdf
http://www.st.com/internet/com/TECHNICAL_RESOURCES/TECHNICAL_LITERATURE/DATA_BRIEF/CD00270920.pdf http://www.st.com/web/en/resource/technical/document/datasheet/CD00225278.pdf
http://www.st.com/web/en/resource/technical/document/datasheet/DM00076709.pdf
* JEDEC JC 42.4 compliant temperature sensor chips * JEDEC JC 42.4 compliant temperature sensor chips
Datasheet: Datasheet:
http://www.jedec.org/sites/default/files/docs/4_01_04R19.pdf http://www.jedec.org/sites/default/files/docs/4_01_04R19.pdf
......
...@@ -18,5 +18,21 @@ sensor incorporates a band-gap type temperature sensor, ...@@ -18,5 +18,21 @@ sensor incorporates a band-gap type temperature sensor,
10-bit ADC, and a digital comparator with user-programmable upper 10-bit ADC, and a digital comparator with user-programmable upper
and lower limit values. and lower limit values.
Limits can be set through the Overtemperature Shutdown register and The LM77 implements 3 limits: low (temp1_min), high (temp1_max) and
Hysteresis register. critical (temp1_crit.) It also implements an hysteresis mechanism which
applies to all 3 limits. The relative difference is stored in a single
register on the chip, which means that the relative difference between
the limit and its hysteresis is always the same for all 3 limits.
This implementation detail implies the following:
* When setting a limit, its hysteresis will automatically follow, the
difference staying unchanged. For example, if the old critical limit
was 80 degrees C, and the hysteresis was 75 degrees C, and you change
the critical limit to 90 degrees C, then the hysteresis will
automatically change to 85 degrees C.
* All 3 hysteresis can't be set independently. We decided to make
temp1_crit_hyst writable, while temp1_min_hyst and temp1_max_hyst are
read-only. Setting temp1_crit_hyst writes the difference between
temp1_crit_hyst and temp1_crit into the chip, and the same relative
hysteresis applies automatically to the low and high limits.
* The limits should be set before the hysteresis.
Kernel driver nct6683
=====================
Supported chips:
* Nuvoton NCT6683D
Prefix: 'nct6683'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
Authors:
Guenter Roeck <linux@roeck-us.net>
Description
-----------
This driver implements support for the Nuvoton NCT6683D eSIO chip.
The chips implement up to shared 32 temperature and voltage sensors.
It supports up to 16 fan rotation sensors and up to 8 fan control engines.
Temperatures are measured in degrees Celsius. Measurement resolution is
0.5 degrees C.
Voltage sensors (also known as IN sensors) report their values in millivolts.
Fan rotation speeds are reported in RPM (rotations per minute).
Usage Note
----------
Limit register locations on Intel boards with EC firmware version 1.0
build date 04/03/13 do not match the register locations in the Nuvoton
datasheet. Nuvoton confirms that Intel uses a special firmware version
with different register addresses. The specification describing the Intel
firmware is held under NDA by Nuvoton and Intel and not available
to the public.
Some of the register locations can be reverse engineered; others are too
well hidden. Given this, writing any values from the operating system is
considered too risky with this firmware and has been disabled. All limits
must all be written from the BIOS.
The driver has only been tested with the Intel firmware, and by default
only instantiates on Intel boards. To enable it on non-Intel boards,
set the 'force' module parameter to 1.
Tested Boards and Firmware Versions
-----------------------------------
The driver has been reported to work with the following boards and
firmware versions.
Board Firmware version
---------------------------------------------------------------
Intel DH87RL NCT6683D EC firmware version 1.0 build 04/03/13
Intel DH87MC NCT6683D EC firmware version 1.0 build 04/03/13
Intel DB85FL NCT6683D EC firmware version 1.0 build 04/03/13
...@@ -355,7 +355,7 @@ F: Documentation/hwmon/adm1025 ...@@ -355,7 +355,7 @@ F: Documentation/hwmon/adm1025
F: drivers/hwmon/adm1025.c F: drivers/hwmon/adm1025.c
ADM1029 HARDWARE MONITOR DRIVER ADM1029 HARDWARE MONITOR DRIVER
M: Corentin Labbe <corentin.labbe@geomatys.fr> M: Corentin Labbe <clabbe.montjoie@gmail.com>
L: lm-sensors@lm-sensors.org L: lm-sensors@lm-sensors.org
S: Maintained S: Maintained
F: drivers/hwmon/adm1029.c F: drivers/hwmon/adm1029.c
......
...@@ -1065,6 +1065,16 @@ config SENSORS_NTC_THERMISTOR ...@@ -1065,6 +1065,16 @@ config SENSORS_NTC_THERMISTOR
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called ntc-thermistor. will be called ntc-thermistor.
config SENSORS_NCT6683
tristate "Nuvoton NCT6683D"
depends on !PPC
help
If you say yes here you get support for the hardware monitoring
functionality of the Nuvoton NCT6683D eSIO chip.
This driver can also be built as a module. If so, the module
will be called nct6683.
config SENSORS_NCT6775 config SENSORS_NCT6775
tristate "Nuvoton NCT6775F and compatibles" tristate "Nuvoton NCT6775F and compatibles"
depends on !PPC depends on !PPC
......
...@@ -114,6 +114,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o ...@@ -114,6 +114,7 @@ obj-$(CONFIG_SENSORS_MAX6650) += max6650.o
obj-$(CONFIG_SENSORS_MAX6697) += max6697.o obj-$(CONFIG_SENSORS_MAX6697) += max6697.o
obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o
obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o obj-$(CONFIG_SENSORS_NTC_THERMISTOR) += ntc_thermistor.o
obj-$(CONFIG_SENSORS_PC87360) += pc87360.o obj-$(CONFIG_SENSORS_PC87360) += pc87360.o
......
/* /*
* adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring * adm1029.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
* *
* Copyright (C) 2006 Corentin LABBE <corentin.labbe@geomatys.fr> * Copyright (C) 2006 Corentin LABBE <clabbe.montjoie@gmail.com>
* *
* Based on LM83 Driver by Jean Delvare <jdelvare@suse.de> * Based on LM83 Driver by Jean Delvare <jdelvare@suse.de>
* *
...@@ -449,6 +449,6 @@ static struct adm1029_data *adm1029_update_device(struct device *dev) ...@@ -449,6 +449,6 @@ static struct adm1029_data *adm1029_update_device(struct device *dev)
module_i2c_driver(adm1029_driver); module_i2c_driver(adm1029_driver);
MODULE_AUTHOR("Corentin LABBE <corentin.labbe@geomatys.fr>"); MODULE_AUTHOR("Corentin LABBE <clabbe.montjoie@gmail.com>");
MODULE_DESCRIPTION("adm1029 driver"); MODULE_DESCRIPTION("adm1029 driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
This diff is collapsed.
...@@ -1387,10 +1387,8 @@ static int f71805f_probe(struct platform_device *pdev) ...@@ -1387,10 +1387,8 @@ static int f71805f_probe(struct platform_device *pdev)
data = devm_kzalloc(&pdev->dev, sizeof(struct f71805f_data), data = devm_kzalloc(&pdev->dev, sizeof(struct f71805f_data),
GFP_KERNEL); GFP_KERNEL);
if (!data) { if (!data)
pr_err("Out of memory\n");
return -ENOMEM; return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!devm_request_region(&pdev->dev, res->start + ADDR_REG_OFFSET, 2, if (!devm_request_region(&pdev->dev, res->start + ADDR_REG_OFFSET, 2,
......
...@@ -586,7 +586,7 @@ static int do_set_fan_startv(struct device *dev, unsigned long val) ...@@ -586,7 +586,7 @@ static int do_set_fan_startv(struct device *dev, unsigned long val)
*/ */
#ifdef CONFIG_OF #ifdef CONFIG_OF
static struct of_device_id g762_dt_match[] = { static const struct of_device_id g762_dt_match[] = {
{ .compatible = "gmt,g762" }, { .compatible = "gmt,g762" },
{ .compatible = "gmt,g763" }, { .compatible = "gmt,g763" },
{ }, { },
......
...@@ -482,7 +482,7 @@ static int gpio_fan_get_of_pdata(struct device *dev, ...@@ -482,7 +482,7 @@ static int gpio_fan_get_of_pdata(struct device *dev,
return 0; return 0;
} }
static struct of_device_id of_gpio_fan_match[] = { static const struct of_device_id of_gpio_fan_match[] = {
{ .compatible = "gpio-fan", }, { .compatible = "gpio-fan", },
{}, {},
}; };
......
...@@ -463,10 +463,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev) ...@@ -463,10 +463,8 @@ static void ibmpex_register_bmc(int iface, struct device *dev)
int err; int err;
data = kzalloc(sizeof(*data), GFP_KERNEL); data = kzalloc(sizeof(*data), GFP_KERNEL);
if (!data) { if (!data)
dev_err(dev, "Insufficient memory for BMC interface.\n");
return; return;
}
data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; data->address.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
data->address.channel = IPMI_BMC_CHANNEL; data->address.channel = IPMI_BMC_CHANNEL;
......
...@@ -163,7 +163,7 @@ static int iio_hwmon_remove(struct platform_device *pdev) ...@@ -163,7 +163,7 @@ static int iio_hwmon_remove(struct platform_device *pdev)
return 0; return 0;
} }
static struct of_device_id iio_hwmon_of_match[] = { static const struct of_device_id iio_hwmon_of_match[] = {
{ .compatible = "iio-hwmon", }, { .compatible = "iio-hwmon", },
{ } { }
}; };
......
This diff is collapsed.
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
#define LM70_CHIP_LM74 3 /* NS LM74 */ #define LM70_CHIP_LM74 3 /* NS LM74 */
struct lm70 { struct lm70 {
struct device *hwmon_dev; struct spi_device *spi;
struct mutex lock; struct mutex lock;
unsigned int chip; unsigned int chip;
}; };
...@@ -56,11 +56,11 @@ struct lm70 { ...@@ -56,11 +56,11 @@ struct lm70 {
static ssize_t lm70_sense_temp(struct device *dev, static ssize_t lm70_sense_temp(struct device *dev,
struct device_attribute *attr, char *buf) struct device_attribute *attr, char *buf)
{ {
struct spi_device *spi = to_spi_device(dev); struct lm70 *p_lm70 = dev_get_drvdata(dev);
struct spi_device *spi = p_lm70->spi;
int status, val = 0; int status, val = 0;
u8 rxbuf[2]; u8 rxbuf[2];
s16 raw = 0; s16 raw = 0;
struct lm70 *p_lm70 = spi_get_drvdata(spi);
if (mutex_lock_interruptible(&p_lm70->lock)) if (mutex_lock_interruptible(&p_lm70->lock))
return -ERESTARTSYS; return -ERESTARTSYS;
...@@ -121,21 +121,20 @@ static ssize_t lm70_sense_temp(struct device *dev, ...@@ -121,21 +121,20 @@ static ssize_t lm70_sense_temp(struct device *dev,
static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL); static DEVICE_ATTR(temp1_input, S_IRUGO, lm70_sense_temp, NULL);
static ssize_t lm70_show_name(struct device *dev, struct device_attribute static struct attribute *lm70_attrs[] = {
*devattr, char *buf) &dev_attr_temp1_input.attr,
{ NULL
return sprintf(buf, "%s\n", to_spi_device(dev)->modalias); };
}
static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); ATTRIBUTE_GROUPS(lm70);
/*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/
static int lm70_probe(struct spi_device *spi) static int lm70_probe(struct spi_device *spi)
{ {
int chip = spi_get_device_id(spi)->driver_data; int chip = spi_get_device_id(spi)->driver_data;
struct device *hwmon_dev;
struct lm70 *p_lm70; struct lm70 *p_lm70;
int status;
/* signaling is SPI_MODE_0 */ /* signaling is SPI_MODE_0 */
if (spi->mode & (SPI_CPOL | SPI_CPHA)) if (spi->mode & (SPI_CPOL | SPI_CPHA))
...@@ -149,46 +148,14 @@ static int lm70_probe(struct spi_device *spi) ...@@ -149,46 +148,14 @@ static int lm70_probe(struct spi_device *spi)
mutex_init(&p_lm70->lock); mutex_init(&p_lm70->lock);
p_lm70->chip = chip; p_lm70->chip = chip;
p_lm70->spi = spi;
spi_set_drvdata(spi, p_lm70); hwmon_dev = devm_hwmon_device_register_with_groups(&spi->dev,
spi->modalias,
status = device_create_file(&spi->dev, &dev_attr_temp1_input); p_lm70, lm70_groups);
if (status) return PTR_ERR_OR_ZERO(hwmon_dev);
goto out_dev_create_temp_file_failed;
status = device_create_file(&spi->dev, &dev_attr_name);
if (status)
goto out_dev_create_file_failed;
/* sysfs hook */
p_lm70->hwmon_dev = hwmon_device_register(&spi->dev);
if (IS_ERR(p_lm70->hwmon_dev)) {
dev_dbg(&spi->dev, "hwmon_device_register failed.\n");
status = PTR_ERR(p_lm70->hwmon_dev);
goto out_dev_reg_failed;
}
return 0;
out_dev_reg_failed:
device_remove_file(&spi->dev, &dev_attr_name);
out_dev_create_file_failed:
device_remove_file(&spi->dev, &dev_attr_temp1_input);
out_dev_create_temp_file_failed:
return status;
} }
static int lm70_remove(struct spi_device *spi)
{
struct lm70 *p_lm70 = spi_get_drvdata(spi);
hwmon_device_unregister(p_lm70->hwmon_dev);
device_remove_file(&spi->dev, &dev_attr_temp1_input);
device_remove_file(&spi->dev, &dev_attr_name);
return 0;
}
static const struct spi_device_id lm70_ids[] = { static const struct spi_device_id lm70_ids[] = {
{ "lm70", LM70_CHIP_LM70 }, { "lm70", LM70_CHIP_LM70 },
{ "tmp121", LM70_CHIP_TMP121 }, { "tmp121", LM70_CHIP_TMP121 },
...@@ -205,7 +172,6 @@ static struct spi_driver lm70_driver = { ...@@ -205,7 +172,6 @@ static struct spi_driver lm70_driver = {
}, },
.id_table = lm70_ids, .id_table = lm70_ids,
.probe = lm70_probe, .probe = lm70_probe,
.remove = lm70_remove,
}; };
module_spi_driver(lm70_driver); module_spi_driver(lm70_driver);
......
...@@ -72,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = { ...@@ -72,6 +72,7 @@ static const u8 LM75_REG_TEMP[3] = {
/* Each client has this additional data */ /* Each client has this additional data */
struct lm75_data { struct lm75_data {
struct i2c_client *client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
struct mutex update_lock; struct mutex update_lock;
...@@ -130,8 +131,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da, ...@@ -130,8 +131,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *da,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct sensor_device_attribute *attr = to_sensor_dev_attr(da); struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
struct i2c_client *client = to_i2c_client(dev); struct lm75_data *data = dev_get_drvdata(dev);
struct lm75_data *data = i2c_get_clientdata(client); struct i2c_client *client = data->client;
int nr = attr->index; int nr = attr->index;
long temp; long temp;
int error; int error;
...@@ -165,17 +166,14 @@ static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, ...@@ -165,17 +166,14 @@ static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO,
show_temp, set_temp, 2); show_temp, set_temp, 2);
static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
static struct attribute *lm75_attributes[] = { static struct attribute *lm75_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
NULL NULL
}; };
ATTRIBUTE_GROUPS(lm75);
static const struct attribute_group lm75_group = {
.attrs = lm75_attributes,
};
/*-----------------------------------------------------------------------*/ /*-----------------------------------------------------------------------*/
...@@ -184,6 +182,7 @@ static const struct attribute_group lm75_group = { ...@@ -184,6 +182,7 @@ static const struct attribute_group lm75_group = {
static int static int
lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev;
struct lm75_data *data; struct lm75_data *data;
int status; int status;
u8 set_mask, clr_mask; u8 set_mask, clr_mask;
...@@ -194,10 +193,11 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -194,10 +193,11 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA)) I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA))
return -EIO; return -EIO;
data = devm_kzalloc(&client->dev, sizeof(struct lm75_data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(struct lm75_data), GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
data->client = client;
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
...@@ -269,7 +269,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -269,7 +269,7 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
/* configure as specified */ /* configure as specified */
status = lm75_read_value(client, LM75_REG_CONF); status = lm75_read_value(client, LM75_REG_CONF);
if (status < 0) { if (status < 0) {
dev_dbg(&client->dev, "Can't read config? %d\n", status); dev_dbg(dev, "Can't read config? %d\n", status);
return status; return status;
} }
data->orig_conf = status; data->orig_conf = status;
...@@ -277,43 +277,32 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -277,43 +277,32 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
new |= set_mask; new |= set_mask;
if (status != new) if (status != new)
lm75_write_value(client, LM75_REG_CONF, new); lm75_write_value(client, LM75_REG_CONF, new);
dev_dbg(&client->dev, "Config %02x\n", new); dev_dbg(dev, "Config %02x\n", new);
/* Register sysfs hooks */ data->hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
status = sysfs_create_group(&client->dev.kobj, &lm75_group); data, lm75_groups);
if (status) if (IS_ERR(data->hwmon_dev))
return status; return PTR_ERR(data->hwmon_dev);
data->hwmon_dev = hwmon_device_register(&client->dev); data->tz = thermal_zone_of_sensor_register(data->hwmon_dev,
if (IS_ERR(data->hwmon_dev)) {
status = PTR_ERR(data->hwmon_dev);
goto exit_remove;
}
data->tz = thermal_zone_of_sensor_register(&client->dev,
0, 0,
&client->dev, data->hwmon_dev,
lm75_read_temp, NULL); lm75_read_temp, NULL);
if (IS_ERR(data->tz)) if (IS_ERR(data->tz))
data->tz = NULL; data->tz = NULL;
dev_info(&client->dev, "%s: sensor '%s'\n", dev_info(dev, "%s: sensor '%s'\n",
dev_name(data->hwmon_dev), client->name); dev_name(data->hwmon_dev), client->name);
return 0; return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &lm75_group);
return status;
} }
static int lm75_remove(struct i2c_client *client) static int lm75_remove(struct i2c_client *client)
{ {
struct lm75_data *data = i2c_get_clientdata(client); struct lm75_data *data = i2c_get_clientdata(client);
thermal_zone_of_sensor_unregister(&client->dev, data->tz); thermal_zone_of_sensor_unregister(data->hwmon_dev, data->tz);
hwmon_device_unregister(data->hwmon_dev); hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm75_group);
lm75_write_value(client, LM75_REG_CONF, data->orig_conf); lm75_write_value(client, LM75_REG_CONF, data->orig_conf);
return 0; return 0;
} }
...@@ -507,8 +496,8 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value) ...@@ -507,8 +496,8 @@ static int lm75_write_value(struct i2c_client *client, u8 reg, u16 value)
static struct lm75_data *lm75_update_device(struct device *dev) static struct lm75_data *lm75_update_device(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct lm75_data *data = dev_get_drvdata(dev);
struct lm75_data *data = i2c_get_clientdata(client); struct i2c_client *client = data->client;
struct lm75_data *ret = data; struct lm75_data *ret = data;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
......
This diff is collapsed.
This diff is collapsed.
...@@ -25,10 +25,6 @@ ...@@ -25,10 +25,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details. * 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/module.h>
...@@ -110,46 +106,13 @@ static const u8 LM83_REG_W_HIGH[] = { ...@@ -110,46 +106,13 @@ static const u8 LM83_REG_W_HIGH[] = {
LM83_REG_W_TCRIT, LM83_REG_W_TCRIT,
}; };
/*
* Functions declaration
*/
static int lm83_detect(struct i2c_client *new_client,
struct i2c_board_info *info);
static int lm83_probe(struct i2c_client *client,
const struct i2c_device_id *id);
static int lm83_remove(struct i2c_client *client);
static struct lm83_data *lm83_update_device(struct device *dev);
/*
* Driver data (common to all clients)
*/
static const struct i2c_device_id lm83_id[] = {
{ "lm83", lm83 },
{ "lm82", lm82 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm83_id);
static struct i2c_driver lm83_driver = {
.class = I2C_CLASS_HWMON,
.driver = {
.name = "lm83",
},
.probe = lm83_probe,
.remove = lm83_remove,
.id_table = lm83_id,
.detect = lm83_detect,
.address_list = normal_i2c,
};
/* /*
* Client data (each client gets its own) * Client data (each client gets its own)
*/ */
struct lm83_data { struct lm83_data {
struct device *hwmon_dev; struct i2c_client *client;
const struct attribute_group *groups[3];
struct mutex update_lock; struct mutex update_lock;
char valid; /* zero until following fields are valid */ char valid; /* zero until following fields are valid */
unsigned long last_updated; /* in jiffies */ unsigned long last_updated; /* in jiffies */
...@@ -161,6 +124,36 @@ struct lm83_data { ...@@ -161,6 +124,36 @@ struct lm83_data {
u16 alarms; /* bitvector, combined */ u16 alarms; /* bitvector, combined */
}; };
static struct lm83_data *lm83_update_device(struct device *dev)
{
struct lm83_data *data = dev_get_drvdata(dev);
struct i2c_client *client = data->client;
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int nr;
dev_dbg(&client->dev, "Updating lm83 data.\n");
for (nr = 0; nr < 9; nr++) {
data->temp[nr] =
i2c_smbus_read_byte_data(client,
LM83_REG_R_TEMP[nr]);
}
data->alarms =
i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
+ (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
<< 8);
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock);
return data;
}
/* /*
* Sysfs stuff * Sysfs stuff
*/ */
...@@ -177,8 +170,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr, ...@@ -177,8 +170,8 @@ static ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
struct i2c_client *client = to_i2c_client(dev); struct lm83_data *data = dev_get_drvdata(dev);
struct lm83_data *data = i2c_get_clientdata(client); struct i2c_client *client = data->client;
long val; long val;
int nr = attr->index; int nr = attr->index;
int err; int err;
...@@ -340,15 +333,15 @@ static int lm83_detect(struct i2c_client *new_client, ...@@ -340,15 +333,15 @@ static int lm83_detect(struct i2c_client *new_client,
static int lm83_probe(struct i2c_client *new_client, static int lm83_probe(struct i2c_client *new_client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *hwmon_dev;
struct lm83_data *data; struct lm83_data *data;
int err;
data = devm_kzalloc(&new_client->dev, sizeof(struct lm83_data), data = devm_kzalloc(&new_client->dev, sizeof(struct lm83_data),
GFP_KERNEL); GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(new_client, data); data->client = new_client;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
/* /*
...@@ -357,72 +350,37 @@ static int lm83_probe(struct i2c_client *new_client, ...@@ -357,72 +350,37 @@ static int lm83_probe(struct i2c_client *new_client,
* at the same register as the LM83 temp3 entry - so we * at the same register as the LM83 temp3 entry - so we
* declare 1 and 3 common, and then 2 and 4 only for the LM83. * declare 1 and 3 common, and then 2 and 4 only for the LM83.
*/ */
data->groups[0] = &lm83_group;
err = sysfs_create_group(&new_client->dev.kobj, &lm83_group); if (id->driver_data == lm83)
if (err) data->groups[1] = &lm83_group_opt;
return err;
hwmon_dev = devm_hwmon_device_register_with_groups(&new_client->dev,
if (id->driver_data == lm83) { new_client->name,
err = sysfs_create_group(&new_client->dev.kobj, data, data->groups);
&lm83_group_opt); return PTR_ERR_OR_ZERO(hwmon_dev);
if (err)
goto exit_remove_files;
}
data->hwmon_dev = hwmon_device_register(&new_client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
goto exit_remove_files;
}
return 0;
exit_remove_files:
sysfs_remove_group(&new_client->dev.kobj, &lm83_group);
sysfs_remove_group(&new_client->dev.kobj, &lm83_group_opt);
return err;
}
static int lm83_remove(struct i2c_client *client)
{
struct lm83_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &lm83_group);
sysfs_remove_group(&client->dev.kobj, &lm83_group_opt);
return 0;
} }
static struct lm83_data *lm83_update_device(struct device *dev) /*
{ * Driver data (common to all clients)
struct i2c_client *client = to_i2c_client(dev); */
struct lm83_data *data = i2c_get_clientdata(client);
mutex_lock(&data->update_lock);
if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
int nr;
dev_dbg(&client->dev, "Updating lm83 data.\n");
for (nr = 0; nr < 9; nr++) {
data->temp[nr] =
i2c_smbus_read_byte_data(client,
LM83_REG_R_TEMP[nr]);
}
data->alarms =
i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS1)
+ (i2c_smbus_read_byte_data(client, LM83_REG_R_STATUS2)
<< 8);
data->last_updated = jiffies;
data->valid = 1;
}
mutex_unlock(&data->update_lock); static const struct i2c_device_id lm83_id[] = {
{ "lm83", lm83 },
{ "lm82", lm82 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm83_id);
return data; static struct i2c_driver lm83_driver = {
} .class = I2C_CLASS_HWMON,
.driver = {
.name = "lm83",
},
.probe = lm83_probe,
.id_table = lm83_id,
.detect = lm83_detect,
.address_list = normal_i2c,
};
module_i2c_driver(lm83_driver); module_i2c_driver(lm83_driver);
......
This diff is collapsed.
...@@ -2747,10 +2747,8 @@ static int lm93_probe(struct i2c_client *client, ...@@ -2747,10 +2747,8 @@ static int lm93_probe(struct i2c_client *client,
} }
data = devm_kzalloc(&client->dev, sizeof(struct lm93_data), GFP_KERNEL); data = devm_kzalloc(&client->dev, sizeof(struct lm93_data), GFP_KERNEL);
if (!data) { if (!data)
dev_dbg(&client->dev, "out of memory!\n");
return -ENOMEM; return -ENOMEM;
}
i2c_set_clientdata(client, data); i2c_set_clientdata(client, data);
/* housekeeping */ /* housekeeping */
......
/* /*
* Driver for Linear Technology LTC2945 I2C Power Monitor * Driver for Linear Technology LTC2945 I2C Power Monitor
* *
* Copyright (c) 2014 Guenter Roeck * Copyright (c) 2014 Guenter Roeck
......
...@@ -192,10 +192,8 @@ static int max1111_probe(struct spi_device *spi) ...@@ -192,10 +192,8 @@ static int max1111_probe(struct spi_device *spi)
return err; return err;
data = devm_kzalloc(&spi->dev, sizeof(struct max1111_data), GFP_KERNEL); data = devm_kzalloc(&spi->dev, sizeof(struct max1111_data), GFP_KERNEL);
if (data == NULL) { if (data == NULL)
dev_err(&spi->dev, "failed to allocate memory\n");
return -ENOMEM; return -ENOMEM;
}
switch (chip) { switch (chip) {
case max1110: case max1110:
......
This diff is collapsed.
...@@ -275,10 +275,8 @@ static int max197_probe(struct platform_device *pdev) ...@@ -275,10 +275,8 @@ static int max197_probe(struct platform_device *pdev)
} }
data = devm_kzalloc(&pdev->dev, sizeof(struct max197_data), GFP_KERNEL); data = devm_kzalloc(&pdev->dev, sizeof(struct max197_data), GFP_KERNEL);
if (!data) { if (!data)
dev_err(&pdev->dev, "devm_kzalloc failed\n");
return -ENOMEM; return -ENOMEM;
}
data->pdata = pdata; data->pdata = pdata;
mutex_init(&data->lock); mutex_init(&data->lock);
......
This diff is collapsed.
...@@ -4160,7 +4160,7 @@ static int __init sensors_nct6775_init(void) ...@@ -4160,7 +4160,7 @@ static int __init sensors_nct6775_init(void)
pdev[i] = platform_device_alloc(DRVNAME, address); pdev[i] = platform_device_alloc(DRVNAME, address);
if (!pdev[i]) { if (!pdev[i]) {
err = -ENOMEM; err = -ENOMEM;
goto exit_device_put; goto exit_device_unregister;
} }
err = platform_device_add_data(pdev[i], &sio_data, err = platform_device_add_data(pdev[i], &sio_data,
...@@ -4198,9 +4198,11 @@ static int __init sensors_nct6775_init(void) ...@@ -4198,9 +4198,11 @@ static int __init sensors_nct6775_init(void)
return 0; return 0;
exit_device_put: exit_device_put:
for (i = 0; i < ARRAY_SIZE(pdev); i++) { platform_device_put(pdev[i]);
exit_device_unregister:
while (--i >= 0) {
if (pdev[i]) if (pdev[i])
platform_device_put(pdev[i]); platform_device_unregister(pdev[i]);
} }
exit_unregister: exit_unregister:
platform_driver_unregister(&nct6775_driver); platform_driver_unregister(&nct6775_driver);
......
...@@ -1081,10 +1081,8 @@ static int pc87427_probe(struct platform_device *pdev) ...@@ -1081,10 +1081,8 @@ static int pc87427_probe(struct platform_device *pdev)
data = devm_kzalloc(&pdev->dev, sizeof(struct pc87427_data), data = devm_kzalloc(&pdev->dev, sizeof(struct pc87427_data),
GFP_KERNEL); GFP_KERNEL);
if (!data) { if (!data)
pr_err("Out of memory\n");
return -ENOMEM; return -ENOMEM;
}
data->address[0] = sio_data->address[0]; data->address[0] = sio_data->address[0];
data->address[1] = sio_data->address[1]; data->address[1] = sio_data->address[1];
......
...@@ -285,10 +285,8 @@ static int s3c_hwmon_probe(struct platform_device *dev) ...@@ -285,10 +285,8 @@ static int s3c_hwmon_probe(struct platform_device *dev)
} }
hwmon = devm_kzalloc(&dev->dev, sizeof(struct s3c_hwmon), GFP_KERNEL); hwmon = devm_kzalloc(&dev->dev, sizeof(struct s3c_hwmon), GFP_KERNEL);
if (hwmon == NULL) { if (hwmon == NULL)
dev_err(&dev->dev, "no memory\n");
return -ENOMEM; return -ENOMEM;
}
platform_set_drvdata(dev, hwmon); platform_set_drvdata(dev, hwmon);
......
...@@ -51,6 +51,7 @@ ...@@ -51,6 +51,7 @@
#define TMP102_THIGH_REG 0x03 #define TMP102_THIGH_REG 0x03
struct tmp102 { struct tmp102 {
struct i2c_client *client;
struct device *hwmon_dev; struct device *hwmon_dev;
struct thermal_zone_device *tz; struct thermal_zone_device *tz;
struct mutex lock; struct mutex lock;
...@@ -77,9 +78,10 @@ static const u8 tmp102_reg[] = { ...@@ -77,9 +78,10 @@ static const u8 tmp102_reg[] = {
TMP102_THIGH_REG, TMP102_THIGH_REG,
}; };
static struct tmp102 *tmp102_update_device(struct i2c_client *client) static struct tmp102 *tmp102_update_device(struct device *dev)
{ {
struct tmp102 *tmp102 = i2c_get_clientdata(client); struct tmp102 *tmp102 = dev_get_drvdata(dev);
struct i2c_client *client = tmp102->client;
mutex_lock(&tmp102->lock); mutex_lock(&tmp102->lock);
if (time_after(jiffies, tmp102->last_update + HZ / 3)) { if (time_after(jiffies, tmp102->last_update + HZ / 3)) {
...@@ -98,7 +100,7 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client) ...@@ -98,7 +100,7 @@ static struct tmp102 *tmp102_update_device(struct i2c_client *client)
static int tmp102_read_temp(void *dev, long *temp) static int tmp102_read_temp(void *dev, long *temp)
{ {
struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev)); struct tmp102 *tmp102 = tmp102_update_device(dev);
*temp = tmp102->temp[0]; *temp = tmp102->temp[0];
...@@ -110,7 +112,7 @@ static ssize_t tmp102_show_temp(struct device *dev, ...@@ -110,7 +112,7 @@ static ssize_t tmp102_show_temp(struct device *dev,
char *buf) char *buf)
{ {
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
struct tmp102 *tmp102 = tmp102_update_device(to_i2c_client(dev)); struct tmp102 *tmp102 = tmp102_update_device(dev);
return sprintf(buf, "%d\n", tmp102->temp[sda->index]); return sprintf(buf, "%d\n", tmp102->temp[sda->index]);
} }
...@@ -120,8 +122,8 @@ static ssize_t tmp102_set_temp(struct device *dev, ...@@ -120,8 +122,8 @@ static ssize_t tmp102_set_temp(struct device *dev,
const char *buf, size_t count) const char *buf, size_t count)
{ {
struct sensor_device_attribute *sda = to_sensor_dev_attr(attr); struct sensor_device_attribute *sda = to_sensor_dev_attr(attr);
struct i2c_client *client = to_i2c_client(dev); struct tmp102 *tmp102 = dev_get_drvdata(dev);
struct tmp102 *tmp102 = i2c_get_clientdata(client); struct i2c_client *client = tmp102->client;
long val; long val;
int status; int status;
...@@ -145,16 +147,13 @@ static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp, ...@@ -145,16 +147,13 @@ static SENSOR_DEVICE_ATTR(temp1_max_hyst, S_IWUSR | S_IRUGO, tmp102_show_temp,
static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp, static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, tmp102_show_temp,
tmp102_set_temp, 2); tmp102_set_temp, 2);
static struct attribute *tmp102_attributes[] = { static struct attribute *tmp102_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr,
NULL NULL
}; };
ATTRIBUTE_GROUPS(tmp102);
static const struct attribute_group tmp102_attr_group = {
.attrs = tmp102_attributes,
};
#define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1) #define TMP102_CONFIG (TMP102_CONF_TM | TMP102_CONF_EM | TMP102_CONF_CR1)
#define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL) #define TMP102_CONFIG_RD_ONLY (TMP102_CONF_R0 | TMP102_CONF_R1 | TMP102_CONF_AL)
...@@ -162,72 +161,68 @@ static const struct attribute_group tmp102_attr_group = { ...@@ -162,72 +161,68 @@ static const struct attribute_group tmp102_attr_group = {
static int tmp102_probe(struct i2c_client *client, static int tmp102_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev;
struct device *hwmon_dev;
struct tmp102 *tmp102; struct tmp102 *tmp102;
int status; int status;
if (!i2c_check_functionality(client->adapter, if (!i2c_check_functionality(client->adapter,
I2C_FUNC_SMBUS_WORD_DATA)) { I2C_FUNC_SMBUS_WORD_DATA)) {
dev_err(&client->dev, dev_err(dev,
"adapter doesn't support SMBus word transactions\n"); "adapter doesn't support SMBus word transactions\n");
return -ENODEV; return -ENODEV;
} }
tmp102 = devm_kzalloc(&client->dev, sizeof(*tmp102), GFP_KERNEL); tmp102 = devm_kzalloc(dev, sizeof(*tmp102), GFP_KERNEL);
if (!tmp102) if (!tmp102)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(client, tmp102); i2c_set_clientdata(client, tmp102);
tmp102->client = client;
status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
if (status < 0) { if (status < 0) {
dev_err(&client->dev, "error reading config register\n"); dev_err(dev, "error reading config register\n");
return status; return status;
} }
tmp102->config_orig = status; tmp102->config_orig = status;
status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, status = i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
TMP102_CONFIG); TMP102_CONFIG);
if (status < 0) { if (status < 0) {
dev_err(&client->dev, "error writing config register\n"); dev_err(dev, "error writing config register\n");
goto fail_restore_config; goto fail_restore_config;
} }
status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG); status = i2c_smbus_read_word_swapped(client, TMP102_CONF_REG);
if (status < 0) { if (status < 0) {
dev_err(&client->dev, "error reading config register\n"); dev_err(dev, "error reading config register\n");
goto fail_restore_config; goto fail_restore_config;
} }
status &= ~TMP102_CONFIG_RD_ONLY; status &= ~TMP102_CONFIG_RD_ONLY;
if (status != TMP102_CONFIG) { if (status != TMP102_CONFIG) {
dev_err(&client->dev, "config settings did not stick\n"); dev_err(dev, "config settings did not stick\n");
status = -ENODEV; status = -ENODEV;
goto fail_restore_config; goto fail_restore_config;
} }
tmp102->last_update = jiffies - HZ; tmp102->last_update = jiffies - HZ;
mutex_init(&tmp102->lock); mutex_init(&tmp102->lock);
status = sysfs_create_group(&client->dev.kobj, &tmp102_attr_group); hwmon_dev = hwmon_device_register_with_groups(dev, client->name,
if (status) { tmp102, tmp102_groups);
dev_dbg(&client->dev, "could not create sysfs files\n"); if (IS_ERR(hwmon_dev)) {
dev_dbg(dev, "unable to register hwmon device\n");
status = PTR_ERR(hwmon_dev);
goto fail_restore_config; goto fail_restore_config;
} }
tmp102->hwmon_dev = hwmon_device_register(&client->dev); tmp102->hwmon_dev = hwmon_dev;
if (IS_ERR(tmp102->hwmon_dev)) { tmp102->tz = thermal_zone_of_sensor_register(hwmon_dev, 0, hwmon_dev,
dev_dbg(&client->dev, "unable to register hwmon device\n");
status = PTR_ERR(tmp102->hwmon_dev);
goto fail_remove_sysfs;
}
tmp102->tz = thermal_zone_of_sensor_register(&client->dev, 0,
&client->dev,
tmp102_read_temp, NULL); tmp102_read_temp, NULL);
if (IS_ERR(tmp102->tz)) if (IS_ERR(tmp102->tz))
tmp102->tz = NULL; tmp102->tz = NULL;
dev_info(&client->dev, "initialized\n"); dev_info(dev, "initialized\n");
return 0; return 0;
fail_remove_sysfs:
sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
fail_restore_config: fail_restore_config:
i2c_smbus_write_word_swapped(client, TMP102_CONF_REG, i2c_smbus_write_word_swapped(client, TMP102_CONF_REG,
tmp102->config_orig); tmp102->config_orig);
...@@ -238,9 +233,8 @@ static int tmp102_remove(struct i2c_client *client) ...@@ -238,9 +233,8 @@ static int tmp102_remove(struct i2c_client *client)
{ {
struct tmp102 *tmp102 = i2c_get_clientdata(client); struct tmp102 *tmp102 = i2c_get_clientdata(client);
thermal_zone_of_sensor_unregister(&client->dev, tmp102->tz); thermal_zone_of_sensor_unregister(tmp102->hwmon_dev, tmp102->tz);
hwmon_device_unregister(tmp102->hwmon_dev); hwmon_device_unregister(tmp102->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &tmp102_attr_group);
/* Stop monitoring if device was stopped originally */ /* Stop monitoring if device was stopped originally */
if (tmp102->config_orig & TMP102_CONF_SD) { if (tmp102->config_orig & TMP102_CONF_SD) {
......
...@@ -69,7 +69,7 @@ static const struct i2c_device_id tmp421_id[] = { ...@@ -69,7 +69,7 @@ static const struct i2c_device_id tmp421_id[] = {
MODULE_DEVICE_TABLE(i2c, tmp421_id); MODULE_DEVICE_TABLE(i2c, tmp421_id);
struct tmp421_data { struct tmp421_data {
struct device *hwmon_dev; struct i2c_client *client;
struct mutex update_lock; struct mutex update_lock;
char valid; char valid;
unsigned long last_updated; unsigned long last_updated;
...@@ -99,8 +99,8 @@ static int temp_from_u16(u16 reg) ...@@ -99,8 +99,8 @@ static int temp_from_u16(u16 reg)
static struct tmp421_data *tmp421_update_device(struct device *dev) static struct tmp421_data *tmp421_update_device(struct device *dev)
{ {
struct i2c_client *client = to_i2c_client(dev); struct tmp421_data *data = dev_get_drvdata(dev);
struct tmp421_data *data = i2c_get_clientdata(client); struct i2c_client *client = data->client;
int i; int i;
mutex_lock(&data->update_lock); mutex_lock(&data->update_lock);
...@@ -198,6 +198,11 @@ static const struct attribute_group tmp421_group = { ...@@ -198,6 +198,11 @@ static const struct attribute_group tmp421_group = {
.is_visible = tmp421_is_visible, .is_visible = tmp421_is_visible,
}; };
static const struct attribute_group *tmp421_groups[] = {
&tmp421_group,
NULL
};
static int tmp421_init_client(struct i2c_client *client) static int tmp421_init_client(struct i2c_client *client)
{ {
int config, config_orig; int config, config_orig;
...@@ -264,47 +269,26 @@ static int tmp421_detect(struct i2c_client *client, ...@@ -264,47 +269,26 @@ static int tmp421_detect(struct i2c_client *client,
static int tmp421_probe(struct i2c_client *client, static int tmp421_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
struct device *dev = &client->dev;
struct device *hwmon_dev;
struct tmp421_data *data; struct tmp421_data *data;
int err; int err;
data = devm_kzalloc(&client->dev, sizeof(struct tmp421_data), data = devm_kzalloc(dev, sizeof(struct tmp421_data), GFP_KERNEL);
GFP_KERNEL);
if (!data) if (!data)
return -ENOMEM; return -ENOMEM;
i2c_set_clientdata(client, data);
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
data->channels = id->driver_data; data->channels = id->driver_data;
data->client = client;
err = tmp421_init_client(client); err = tmp421_init_client(client);
if (err) if (err)
return err; return err;
err = sysfs_create_group(&client->dev.kobj, &tmp421_group); hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
if (err) data, tmp421_groups);
return err; return PTR_ERR_OR_ZERO(hwmon_dev);
data->hwmon_dev = hwmon_device_register(&client->dev);
if (IS_ERR(data->hwmon_dev)) {
err = PTR_ERR(data->hwmon_dev);
data->hwmon_dev = NULL;
goto exit_remove;
}
return 0;
exit_remove:
sysfs_remove_group(&client->dev.kobj, &tmp421_group);
return err;
}
static int tmp421_remove(struct i2c_client *client)
{
struct tmp421_data *data = i2c_get_clientdata(client);
hwmon_device_unregister(data->hwmon_dev);
sysfs_remove_group(&client->dev.kobj, &tmp421_group);
return 0;
} }
static struct i2c_driver tmp421_driver = { static struct i2c_driver tmp421_driver = {
...@@ -313,7 +297,6 @@ static struct i2c_driver tmp421_driver = { ...@@ -313,7 +297,6 @@ static struct i2c_driver tmp421_driver = {
.name = "tmp421", .name = "tmp421",
}, },
.probe = tmp421_probe, .probe = tmp421_probe,
.remove = tmp421_remove,
.id_table = tmp421_id, .id_table = tmp421_id,
.detect = tmp421_detect, .detect = tmp421_detect,
.address_list = normal_i2c, .address_list = normal_i2c,
......
...@@ -252,7 +252,7 @@ static const struct attribute_group env_group = { ...@@ -252,7 +252,7 @@ static const struct attribute_group env_group = {
static int env_probe(struct platform_device *op) static int env_probe(struct platform_device *op)
{ {
struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); struct env *p = devm_kzalloc(&op->dev, sizeof(*p), GFP_KERNEL);
int err = -ENOMEM; int err = -ENOMEM;
if (!p) if (!p)
...@@ -262,7 +262,7 @@ static int env_probe(struct platform_device *op) ...@@ -262,7 +262,7 @@ static int env_probe(struct platform_device *op)
p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747"); p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747");
if (!p->regs) if (!p->regs)
goto out_free; goto out;
err = sysfs_create_group(&op->dev.kobj, &env_group); err = sysfs_create_group(&op->dev.kobj, &env_group);
if (err) if (err)
...@@ -286,8 +286,6 @@ static int env_probe(struct platform_device *op) ...@@ -286,8 +286,6 @@ static int env_probe(struct platform_device *op)
out_iounmap: out_iounmap:
of_iounmap(&op->resource[0], p->regs, REG_SIZE); of_iounmap(&op->resource[0], p->regs, REG_SIZE);
out_free:
kfree(p);
goto out; goto out;
} }
...@@ -299,7 +297,6 @@ static int env_remove(struct platform_device *op) ...@@ -299,7 +297,6 @@ static int env_remove(struct platform_device *op)
sysfs_remove_group(&op->dev.kobj, &env_group); sysfs_remove_group(&op->dev.kobj, &env_group);
hwmon_device_unregister(p->hwmon_dev); hwmon_device_unregister(p->hwmon_dev);
of_iounmap(&op->resource[0], p->regs, REG_SIZE); of_iounmap(&op->resource[0], p->regs, REG_SIZE);
kfree(p);
} }
return 0; return 0;
......
...@@ -1152,10 +1152,8 @@ static int vt1211_probe(struct platform_device *pdev) ...@@ -1152,10 +1152,8 @@ static int vt1211_probe(struct platform_device *pdev)
int i, err; int i, err;
data = devm_kzalloc(dev, sizeof(struct vt1211_data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(struct vt1211_data), GFP_KERNEL);
if (!data) { if (!data)
dev_err(dev, "Out of memory\n");
return -ENOMEM; return -ENOMEM;
}
res = platform_get_resource(pdev, IORESOURCE_IO, 0); res = platform_get_resource(pdev, IORESOURCE_IO, 0);
if (!devm_request_region(dev, res->start, resource_size(res), if (!devm_request_region(dev, res->start, resource_size(res),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment