Commit 177808cd authored by Linus Torvalds's avatar Linus Torvalds

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

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

Pull hwmon updates from Guenter Roeck:
 "Notable changes:
   - new driver for NCT7802Y
   - support for TMP435, LM95233, LM95235, NCT6792D, and NXP LM75B
   - regulator support for PMBus chips, specifically LTX2978
   - support for humidity sensors to iio-hwmon bridge driver

* tag 'hwmon-for-linus-3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/groeck/linux-staging: (21 commits)
  hwmon: (tmp401) Detect TMP435 on all addresses it supports
  hwmon: (lm75) Strengthen detect function
  hwmon: (gpio-fan) Add a shutdown handler to poweroff the fans
  hwmon: (gpio-fan) Allow usage of gpio operations that may sleep
  hwmon: (tmp401) Bail out from tmp401_probe() in case of write errors
  hwmon: (tmp401) Add support for TI TMP435
  hwmon: (lm95234) Add support for LM95233
  hwmon: (lm95245) Add support for LM95235
  hwmon: (ina2xx) bail-out from ina2xx_probe() in case of configuration errors
  hwmon: (nct6775) Add blank lines after declarations
  hwmon: (nct6775) Add support for NCT6792D
  hwmon: (nct6775) Documentation updates
  hwmon: (lm75) Add support for the NXP LM75B
  hwmon: Driver for Nuvoton NCT7802Y
  hwmon: (ibmpowernv) Convert to module_platform_driver
  hwmon: (ibmpowernv) Use platform 'id_table' to probe the device
  hwmon: (iio_hwmon) Add support for humidity sensors
  hwmon: (ltc2978) Add regulator support
  hwmon: (pmbus) Add regulator support
  hwmon: (pmbus) add helpers for byte write and read modify write
  ...
parents 0160928e 907a6d58
ltc2978
Required properties:
- compatible: should contain one of:
* "lltc,ltc2974"
* "lltc,ltc2977"
* "lltc,ltc2978"
* "lltc,ltc3880"
* "lltc,ltc3883"
* "lltc,ltm4676"
- reg: I2C slave address
Optional properties:
- regulators: A node that houses a sub-node for each regulator controlled by
the device. Each sub-node is identified using the node's name, with valid
values listed below. The content of each sub-node is defined by the
standard binding for regulators; see regulator.txt.
Valid names of regulators depend on number of supplies supported per device:
* ltc2974 : vout0 - vout3
* ltc2977 : vout0 - vout7
* ltc2978 : vout0 - vout7
* ltc3880 : vout0 - vout1
* ltc3883 : vout0
* ltm4676 : vout0 - vout1
Example:
ltc2978@5e {
compatible = "lltc,ltc2978";
reg = <0x5e>;
regulators {
vout0 {
regulator-name = "FPGA-2.5V";
};
vout2 {
regulator-name = "FPGA-1.5V";
};
};
};
...@@ -53,6 +53,11 @@ Supported chips: ...@@ -53,6 +53,11 @@ Supported chips:
http://www.ti.com/product/tmp75 http://www.ti.com/product/tmp75
http://www.ti.com/product/tmp175 http://www.ti.com/product/tmp175
http://www.ti.com/product/tmp275 http://www.ti.com/product/tmp275
* NXP LM75B
Prefix: 'lm75b'
Addresses scanned: none
Datasheet: Publicly available at the NXP website
http://www.nxp.com/documents/data_sheet/LM75B.pdf
Author: Frodo Looijaard <frodol@dds.nl> Author: Frodo Looijaard <frodol@dds.nl>
......
...@@ -2,6 +2,10 @@ Kernel driver lm95234 ...@@ -2,6 +2,10 @@ Kernel driver lm95234
===================== =====================
Supported chips: Supported chips:
* National Semiconductor / Texas Instruments LM95233
Addresses scanned: I2C 0x18, 0x2a, 0x2b
Datasheet: Publicly available at the Texas Instruments website
http://www.ti.com/product/lm95233
* National Semiconductor / Texas Instruments LM95234 * National Semiconductor / Texas Instruments LM95234
Addresses scanned: I2C 0x18, 0x4d, 0x4e Addresses scanned: I2C 0x18, 0x4d, 0x4e
Datasheet: Publicly available at the Texas Instruments website Datasheet: Publicly available at the Texas Instruments website
...@@ -13,11 +17,12 @@ Author: Guenter Roeck <linux@roeck-us.net> ...@@ -13,11 +17,12 @@ Author: Guenter Roeck <linux@roeck-us.net>
Description Description
----------- -----------
LM95234 is an 11-bit digital temperature sensor with a 2-wire System Management LM95233 and LM95234 are 11-bit digital temperature sensors with a 2-wire
Bus (SMBus) interface and TrueTherm technology that can very accurately monitor System Management Bus (SMBus) interface and TrueTherm technology
the temperature of four remote diodes as well as its own temperature. that can very accurately monitor the temperature of two (LM95233)
The four remote diodes can be external devices such as microprocessors, or four (LM95234) remote diodes as well as its own temperature.
graphics processors or diode-connected 2N3904s. The LM95234's TruTherm The remote diodes can be external devices such as microprocessors,
graphics processors or diode-connected 2N3904s. The chip's TruTherm
beta compensation technology allows sensing of 90 nm or 65 nm process beta compensation technology allows sensing of 90 nm or 65 nm process
thermal diodes accurately. thermal diodes accurately.
......
...@@ -2,10 +2,14 @@ Kernel driver lm95245 ...@@ -2,10 +2,14 @@ Kernel driver lm95245
================== ==================
Supported chips: Supported chips:
* National Semiconductor LM95245 * TI LM95235
Addresses scanned: I2C 0x18, 0x29, 0x4c
Datasheet: Publicly available at the TI website
http://www.ti.com/lit/ds/symlink/lm95235.pdf
* TI / National Semiconductor LM95245
Addresses scanned: I2C 0x18, 0x19, 0x29, 0x4c, 0x4d Addresses scanned: I2C 0x18, 0x19, 0x29, 0x4c, 0x4d
Datasheet: Publicly available at the National Semiconductor website Datasheet: Publicly available at the TI website
http://www.national.com/mpf/LM/LM95245.html http://www.ti.com/lit/ds/symlink/lm95245.pdf
Author: Alexander Stein <alexander.stein@systec-electronic.com> Author: Alexander Stein <alexander.stein@systec-electronic.com>
...@@ -13,10 +17,10 @@ Author: Alexander Stein <alexander.stein@systec-electronic.com> ...@@ -13,10 +17,10 @@ Author: Alexander Stein <alexander.stein@systec-electronic.com>
Description Description
----------- -----------
The LM95245 is an 11-bit digital temperature sensor with a 2-wire System LM95235 and LM95245 are 11-bit digital temperature sensors with a 2-wire System
Management Bus (SMBus) interface and TruTherm technology that can monitor Management Bus (SMBus) interface and TruTherm technology that can monitor
the temperature of a remote diode as well as its own temperature. the temperature of a remote diode as well as its own temperature.
The LM95245 can be used to very accurately monitor the temperature of The chips can be used to very accurately monitor the temperature of
external devices such as microprocessors. external devices such as microprocessors.
All temperature values are given in millidegrees Celsius. Local temperature All temperature values are given in millidegrees Celsius. Local temperature
......
...@@ -8,11 +8,15 @@ Kernel driver NCT6775 ...@@ -8,11 +8,15 @@ Kernel driver NCT6775
===================== =====================
Supported chips: Supported chips:
* Nuvoton NCT6102D/NCT6104D/NCT6106D
Prefix: 'nct6106'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from the Nuvoton web site
* Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I * Nuvoton NCT5572D/NCT6771F/NCT6772F/NCT6775F/W83677HG-I
Prefix: 'nct6775' Prefix: 'nct6775'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request Datasheet: Available from Nuvoton upon request
* Nuvoton NCT5577D/NCT6776D/NCT6776F * Nuvoton NCT5573D/NCT5577D/NCT6776D/NCT6776F
Prefix: 'nct6776' Prefix: 'nct6776'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request Datasheet: Available from Nuvoton upon request
...@@ -20,6 +24,14 @@ Supported chips: ...@@ -20,6 +24,14 @@ Supported chips:
Prefix: 'nct6779' Prefix: 'nct6779'
Addresses scanned: ISA address retrieved from Super I/O registers Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request Datasheet: Available from Nuvoton upon request
* Nuvoton NCT6791D
Prefix: 'nct6791'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
* Nuvoton NCT6792D
Prefix: 'nct6792'
Addresses scanned: ISA address retrieved from Super I/O registers
Datasheet: Available from Nuvoton upon request
Authors: Authors:
Guenter Roeck <linux@roeck-us.net> Guenter Roeck <linux@roeck-us.net>
......
Kernel driver nct7802
=====================
Supported chips:
* Nuvoton NCT7802Y
Prefix: 'nct7802'
Addresses scanned: I2C 0x28..0x2f
Datasheet: Available from Nuvoton web site
Authors:
Guenter Roeck <linux@roeck-us.net>
Description
-----------
This driver implements support for the Nuvoton NCT7802Y hardware monitoring
chip. NCT7802Y supports 6 temperature sensors, 5 voltage sensors, and 3 fan
speed sensors.
The chip also supports intelligent fan speed control. This functionality is
not currently supported by the driver.
Tested Boards and BIOS Versions
-------------------------------
The driver has been reported to work with the following boards and
BIOS versions.
Board BIOS version
---------------------------------------------------------------
Kontron COMe-bSC2 CHR2E934.001.GGO
Kontron COMe-bIP2 CCR2E212
...@@ -18,6 +18,10 @@ Supported chips: ...@@ -18,6 +18,10 @@ Supported chips:
Prefix: 'tmp432' Prefix: 'tmp432'
Addresses scanned: I2C 0x4c, 0x4d Addresses scanned: I2C 0x4c, 0x4d
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp432.html Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp432.html
* Texas Instruments TMP435
Prefix: 'tmp435'
Addresses scanned: I2C 0x37, 0x48 - 0x4f
Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp435.html
Authors: Authors:
Hans de Goede <hdegoede@redhat.com> Hans de Goede <hdegoede@redhat.com>
...@@ -27,8 +31,8 @@ Description ...@@ -27,8 +31,8 @@ Description
----------- -----------
This driver implements support for Texas Instruments TMP401, TMP411, This driver implements support for Texas Instruments TMP401, TMP411,
TMP431, and TMP432 chips. These chips implement one or two remote and TMP431, TMP432 and TMP435 chips. These chips implement one or two remote
one local temperature sensors. Temperature is measured in degrees and one local temperature sensors. Temperature is measured in degrees
Celsius. Resolution of the remote sensor is 0.0625 degree. Local Celsius. Resolution of the remote sensor is 0.0625 degree. Local
sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not sensor resolution can be set to 0.5, 0.25, 0.125 or 0.0625 degree (not
supported by the driver so far, so using the default resolution of 0.5 supported by the driver so far, so using the default resolution of 0.5
......
...@@ -20,7 +20,9 @@ ...@@ -20,7 +20,9 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/of_platform.h>
#include <asm/opal.h> #include <asm/opal.h>
#include <asm/machdep.h>
static DEFINE_MUTEX(opal_sensor_mutex); static DEFINE_MUTEX(opal_sensor_mutex);
...@@ -64,3 +66,21 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data) ...@@ -64,3 +66,21 @@ int opal_get_sensor_data(u32 sensor_hndl, u32 *sensor_data)
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(opal_get_sensor_data); EXPORT_SYMBOL_GPL(opal_get_sensor_data);
static __init int opal_sensor_init(void)
{
struct platform_device *pdev;
struct device_node *sensor;
sensor = of_find_node_by_path("/ibm,opal/sensors");
if (!sensor) {
pr_err("Opal node 'sensors' not found\n");
return -ENODEV;
}
pdev = of_platform_device_create(sensor, "opal-sensor", NULL);
of_node_put(sensor);
return PTR_ERR_OR_ZERO(pdev);
}
machine_subsys_initcall(powernv, opal_sensor_init);
...@@ -1028,11 +1028,11 @@ config SENSORS_LM93 ...@@ -1028,11 +1028,11 @@ config SENSORS_LM93
will be called lm93. will be called lm93.
config SENSORS_LM95234 config SENSORS_LM95234
tristate "National Semiconductor LM95234" tristate "National Semiconductor LM95234 and compatibles"
depends on I2C depends on I2C
help help
If you say yes here you get support for the LM95234 temperature If you say yes here you get support for the LM95233 and LM95234
sensor. temperature sensor chips.
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 lm95234. will be called lm95234.
...@@ -1048,10 +1048,11 @@ config SENSORS_LM95241 ...@@ -1048,10 +1048,11 @@ config SENSORS_LM95241
will be called lm95241. will be called lm95241.
config SENSORS_LM95245 config SENSORS_LM95245
tristate "National Semiconductor LM95245 sensor chip" tristate "National Semiconductor LM95245 and compatibles"
depends on I2C depends on I2C
help help
If you say yes here you get support for LM95245 sensor chip. If you say yes here you get support for LM95235 and LM95245
temperature sensor chips.
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 lm95245. will be called lm95245.
...@@ -1117,12 +1118,23 @@ config SENSORS_NCT6775 ...@@ -1117,12 +1118,23 @@ config SENSORS_NCT6775
help help
If you say yes here you get support for the hardware monitoring If you say yes here you get support for the hardware monitoring
functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D, functionality of the Nuvoton NCT6106D, NCT6775F, NCT6776F, NCT6779D,
NCT6791D and compatible Super-I/O chips. This driver replaces the NCT6791D, NCT6792D and compatible Super-I/O chips. This driver
w83627ehf driver for NCT6775F and NCT6776F. replaces the w83627ehf driver for NCT6775F and NCT6776F.
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 nct6775. will be called nct6775.
config SENSORS_NCT7802
tristate "Nuvoton NCT7802Y"
depends on I2C
select REGMAP_I2C
help
If you say yes here you get support for the Nuvoton NCT7802Y
hardware monitoring chip.
This driver can also be built as a module. If so, the module
will be called nct7802.
config SENSORS_PCF8591 config SENSORS_PCF8591
tristate "Philips PCF8591 ADC/DAC" tristate "Philips PCF8591 ADC/DAC"
depends on I2C depends on I2C
...@@ -1454,7 +1466,7 @@ config SENSORS_TMP401 ...@@ -1454,7 +1466,7 @@ config SENSORS_TMP401
depends on I2C depends on I2C
help help
If you say yes here you get support for Texas Instruments TMP401, If you say yes here you get support for Texas Instruments TMP401,
TMP411, TMP431, and TMP432 temperature sensor chips. TMP411, TMP431, TMP432 and TMP435 temperature sensor chips.
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 tmp401. will be called tmp401.
......
...@@ -118,6 +118,7 @@ obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o ...@@ -118,6 +118,7 @@ obj-$(CONFIG_SENSORS_MCP3021) += mcp3021.o
obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o obj-$(CONFIG_SENSORS_MENF21BMC_HWMON) += menf21bmc_hwmon.o
obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o obj-$(CONFIG_SENSORS_NCT6683) += nct6683.o
obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o obj-$(CONFIG_SENSORS_NCT6775) += nct6775.o
obj-$(CONFIG_SENSORS_NCT7802) += nct7802.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
obj-$(CONFIG_SENSORS_PC87427) += pc87427.o obj-$(CONFIG_SENSORS_PC87427) += pc87427.o
......
...@@ -79,7 +79,7 @@ static ssize_t show_fan_alarm(struct device *dev, ...@@ -79,7 +79,7 @@ static ssize_t show_fan_alarm(struct device *dev,
{ {
struct gpio_fan_data *fan_data = dev_get_drvdata(dev); struct gpio_fan_data *fan_data = dev_get_drvdata(dev);
struct gpio_fan_alarm *alarm = fan_data->alarm; struct gpio_fan_alarm *alarm = fan_data->alarm;
int value = gpio_get_value(alarm->gpio); int value = gpio_get_value_cansleep(alarm->gpio);
if (alarm->active_low) if (alarm->active_low)
value = !value; value = !value;
...@@ -131,7 +131,7 @@ static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val) ...@@ -131,7 +131,7 @@ static void __set_fan_ctrl(struct gpio_fan_data *fan_data, int ctrl_val)
int i; int i;
for (i = 0; i < fan_data->num_ctrl; i++) for (i = 0; i < fan_data->num_ctrl; i++)
gpio_set_value(fan_data->ctrl[i], (ctrl_val >> i) & 1); gpio_set_value_cansleep(fan_data->ctrl[i], (ctrl_val >> i) & 1);
} }
static int __get_fan_ctrl(struct gpio_fan_data *fan_data) static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
...@@ -142,7 +142,7 @@ static int __get_fan_ctrl(struct gpio_fan_data *fan_data) ...@@ -142,7 +142,7 @@ static int __get_fan_ctrl(struct gpio_fan_data *fan_data)
for (i = 0; i < fan_data->num_ctrl; i++) { for (i = 0; i < fan_data->num_ctrl; i++) {
int value; int value;
value = gpio_get_value(fan_data->ctrl[i]); value = gpio_get_value_cansleep(fan_data->ctrl[i]);
ctrl_val |= (value << i); ctrl_val |= (value << i);
} }
return ctrl_val; return ctrl_val;
...@@ -369,7 +369,8 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data, ...@@ -369,7 +369,8 @@ static int fan_ctrl_init(struct gpio_fan_data *fan_data,
if (err) if (err)
return err; return err;
err = gpio_direction_output(ctrl[i], gpio_get_value(ctrl[i])); err = gpio_direction_output(ctrl[i],
gpio_get_value_cansleep(ctrl[i]));
if (err) if (err)
return err; return err;
} }
...@@ -549,6 +550,14 @@ static int gpio_fan_probe(struct platform_device *pdev) ...@@ -549,6 +550,14 @@ static int gpio_fan_probe(struct platform_device *pdev)
return 0; return 0;
} }
static void gpio_fan_shutdown(struct platform_device *pdev)
{
struct gpio_fan_data *fan_data = dev_get_drvdata(&pdev->dev);
if (fan_data->ctrl)
set_fan_speed(fan_data, 0);
}
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
static int gpio_fan_suspend(struct device *dev) static int gpio_fan_suspend(struct device *dev)
{ {
...@@ -580,6 +589,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume); ...@@ -580,6 +589,7 @@ static SIMPLE_DEV_PM_OPS(gpio_fan_pm, gpio_fan_suspend, gpio_fan_resume);
static struct platform_driver gpio_fan_driver = { static struct platform_driver gpio_fan_driver = {
.probe = gpio_fan_probe, .probe = gpio_fan_probe,
.shutdown = gpio_fan_shutdown,
.driver = { .driver = {
.name = "gpio-fan", .name = "gpio-fan",
.pm = GPIO_FAN_PM, .pm = GPIO_FAN_PM,
......
...@@ -74,9 +74,6 @@ struct platform_data { ...@@ -74,9 +74,6 @@ struct platform_data {
u32 sensors_count; /* Total count of sensors from each group */ u32 sensors_count; /* Total count of sensors from each group */
}; };
/* Platform device representing all the ibmpowernv sensors */
static struct platform_device *pdevice;
static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
char *buf) char *buf)
{ {
...@@ -99,7 +96,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr, ...@@ -99,7 +96,7 @@ static ssize_t show_sensor(struct device *dev, struct device_attribute *devattr,
return sprintf(buf, "%u\n", x); return sprintf(buf, "%u\n", x);
} }
static int __init get_sensor_index_attr(const char *name, u32 *index, static int get_sensor_index_attr(const char *name, u32 *index,
char *attr) char *attr)
{ {
char *hash_pos = strchr(name, '#'); char *hash_pos = strchr(name, '#');
...@@ -136,7 +133,7 @@ static int __init get_sensor_index_attr(const char *name, u32 *index, ...@@ -136,7 +133,7 @@ static int __init get_sensor_index_attr(const char *name, u32 *index,
* which need to be mapped as fan2_input, temp1_max respectively before * which need to be mapped as fan2_input, temp1_max respectively before
* populating them inside hwmon device class. * populating them inside hwmon device class.
*/ */
static int __init create_hwmon_attr_name(struct device *dev, enum sensors type, static int create_hwmon_attr_name(struct device *dev, enum sensors type,
const char *node_name, const char *node_name,
char *hwmon_attr_name) char *hwmon_attr_name)
{ {
...@@ -172,7 +169,7 @@ static int __init create_hwmon_attr_name(struct device *dev, enum sensors type, ...@@ -172,7 +169,7 @@ static int __init create_hwmon_attr_name(struct device *dev, enum sensors type,
return 0; return 0;
} }
static int __init populate_attr_groups(struct platform_device *pdev) static int populate_attr_groups(struct platform_device *pdev)
{ {
struct platform_data *pdata = platform_get_drvdata(pdev); struct platform_data *pdata = platform_get_drvdata(pdev);
const struct attribute_group **pgroups = pdata->attr_groups; const struct attribute_group **pgroups = pdata->attr_groups;
...@@ -180,11 +177,6 @@ static int __init populate_attr_groups(struct platform_device *pdev) ...@@ -180,11 +177,6 @@ static int __init populate_attr_groups(struct platform_device *pdev)
enum sensors type; enum sensors type;
opal = of_find_node_by_path("/ibm,opal/sensors"); opal = of_find_node_by_path("/ibm,opal/sensors");
if (!opal) {
dev_dbg(&pdev->dev, "Opal node 'sensors' not found\n");
return -ENODEV;
}
for_each_child_of_node(opal, np) { for_each_child_of_node(opal, np) {
if (np->name == NULL) if (np->name == NULL)
continue; continue;
...@@ -221,7 +213,7 @@ static int __init populate_attr_groups(struct platform_device *pdev) ...@@ -221,7 +213,7 @@ static int __init populate_attr_groups(struct platform_device *pdev)
* to the name required by the higher 'hwmon' driver like fan1_input, temp1_max * to the name required by the higher 'hwmon' driver like fan1_input, temp1_max
* etc.. * etc..
*/ */
static int __init create_device_attrs(struct platform_device *pdev) static int create_device_attrs(struct platform_device *pdev)
{ {
struct platform_data *pdata = platform_get_drvdata(pdev); struct platform_data *pdata = platform_get_drvdata(pdev);
const struct attribute_group **pgroups = pdata->attr_groups; const struct attribute_group **pgroups = pdata->attr_groups;
...@@ -280,7 +272,7 @@ static int __init create_device_attrs(struct platform_device *pdev) ...@@ -280,7 +272,7 @@ static int __init create_device_attrs(struct platform_device *pdev)
return err; return err;
} }
static int __init ibmpowernv_probe(struct platform_device *pdev) static int ibmpowernv_probe(struct platform_device *pdev)
{ {
struct platform_data *pdata; struct platform_data *pdata;
struct device *hwmon_dev; struct device *hwmon_dev;
...@@ -309,57 +301,25 @@ static int __init ibmpowernv_probe(struct platform_device *pdev) ...@@ -309,57 +301,25 @@ static int __init ibmpowernv_probe(struct platform_device *pdev)
return PTR_ERR_OR_ZERO(hwmon_dev); return PTR_ERR_OR_ZERO(hwmon_dev);
} }
static struct platform_driver ibmpowernv_driver = { static const struct platform_device_id opal_sensor_driver_ids[] = {
.driver = { {
.owner = THIS_MODULE, .name = "opal-sensor",
.name = DRVNAME,
}, },
{ }
}; };
MODULE_DEVICE_TABLE(platform, opal_sensor_driver_ids);
static int __init ibmpowernv_init(void) static struct platform_driver ibmpowernv_driver = {
{ .probe = ibmpowernv_probe,
int err; .id_table = opal_sensor_driver_ids,
.driver = {
pdevice = platform_device_alloc(DRVNAME, 0); .owner = THIS_MODULE,
if (!pdevice) { .name = DRVNAME,
pr_err("Device allocation failed\n"); },
err = -ENOMEM; };
goto exit;
}
err = platform_device_add(pdevice);
if (err) {
pr_err("Device addition failed (%d)\n", err);
goto exit_device_put;
}
err = platform_driver_probe(&ibmpowernv_driver, ibmpowernv_probe);
if (err) {
if (err != -ENODEV)
pr_err("Platform driver probe failed (%d)\n", err);
goto exit_device_del;
}
return 0;
exit_device_del:
platform_device_del(pdevice);
exit_device_put:
platform_device_put(pdevice);
exit:
return err;
}
static void __exit ibmpowernv_exit(void) module_platform_driver(ibmpowernv_driver);
{
platform_driver_unregister(&ibmpowernv_driver);
platform_device_unregister(pdevice);
}
MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>"); MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
MODULE_DESCRIPTION("IBM POWERNV platform sensors"); MODULE_DESCRIPTION("IBM POWERNV platform sensors");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_init(ibmpowernv_init);
module_exit(ibmpowernv_exit);
...@@ -63,7 +63,7 @@ static int iio_hwmon_probe(struct platform_device *pdev) ...@@ -63,7 +63,7 @@ static int iio_hwmon_probe(struct platform_device *pdev)
struct iio_hwmon_state *st; struct iio_hwmon_state *st;
struct sensor_device_attribute *a; struct sensor_device_attribute *a;
int ret, i; int ret, i;
int in_i = 1, temp_i = 1, curr_i = 1; int in_i = 1, temp_i = 1, curr_i = 1, humidity_i = 1;
enum iio_chan_type type; enum iio_chan_type type;
struct iio_channel *channels; struct iio_channel *channels;
const char *name = "iio_hwmon"; const char *name = "iio_hwmon";
...@@ -123,6 +123,11 @@ static int iio_hwmon_probe(struct platform_device *pdev) ...@@ -123,6 +123,11 @@ static int iio_hwmon_probe(struct platform_device *pdev)
"curr%d_input", "curr%d_input",
curr_i++); curr_i++);
break; break;
case IIO_HUMIDITYRELATIVE:
a->dev_attr.attr.name = kasprintf(GFP_KERNEL,
"humidity%d_input",
humidity_i++);
break;
default: default:
ret = -EINVAL; ret = -EINVAL;
goto error_release_channels; goto error_release_channels;
......
...@@ -223,6 +223,7 @@ static int ina2xx_probe(struct i2c_client *client, ...@@ -223,6 +223,7 @@ static int ina2xx_probe(struct i2c_client *client,
struct device *hwmon_dev; struct device *hwmon_dev;
long shunt = 10000; /* default shunt value 10mOhms */ long shunt = 10000; /* default shunt value 10mOhms */
u32 val; u32 val;
int ret;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA))
return -ENODEV; return -ENODEV;
...@@ -247,12 +248,25 @@ static int ina2xx_probe(struct i2c_client *client, ...@@ -247,12 +248,25 @@ static int ina2xx_probe(struct i2c_client *client,
data->config = &ina2xx_config[data->kind]; data->config = &ina2xx_config[data->kind];
/* device configuration */ /* device configuration */
i2c_smbus_write_word_swapped(client, INA2XX_CONFIG, ret = i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
data->config->config_default); data->config->config_default);
/* set current LSB to 1mA, shunt is in uOhms */ if (ret < 0) {
/* (equation 13 in datasheet) */ dev_err(dev,
i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION, "error writing to the config register: %d", ret);
data->config->calibration_factor / shunt); return -ENODEV;
}
/*
* Set current LSB to 1mA, shunt is in uOhms
* (equation 13 in datasheet).
*/
ret = i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
data->config->calibration_factor / shunt);
if (ret < 0) {
dev_err(dev,
"error writing to the calibration register: %d", ret);
return -ENODEV;
}
data->client = client; data->client = client;
mutex_init(&data->update_lock); mutex_init(&data->update_lock);
......
...@@ -44,6 +44,7 @@ enum lm75_type { /* keep sorted in alphabetical order */ ...@@ -44,6 +44,7 @@ enum lm75_type { /* keep sorted in alphabetical order */
g751, g751,
lm75, lm75,
lm75a, lm75a,
lm75b,
max6625, max6625,
max6626, max6626,
mcp980x, mcp980x,
...@@ -233,6 +234,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id) ...@@ -233,6 +234,10 @@ lm75_probe(struct i2c_client *client, const struct i2c_device_id *id)
data->resolution = 9; data->resolution = 9;
data->sample_time = HZ / 2; data->sample_time = HZ / 2;
break; break;
case lm75b:
data->resolution = 11;
data->sample_time = HZ / 4;
break;
case max6625: case max6625:
data->resolution = 9; data->resolution = 9;
data->sample_time = HZ / 4; data->sample_time = HZ / 4;
...@@ -322,6 +327,7 @@ static const struct i2c_device_id lm75_ids[] = { ...@@ -322,6 +327,7 @@ static const struct i2c_device_id lm75_ids[] = {
{ "g751", g751, }, { "g751", g751, },
{ "lm75", lm75, }, { "lm75", lm75, },
{ "lm75a", lm75a, }, { "lm75a", lm75a, },
{ "lm75b", lm75b, },
{ "max6625", max6625, }, { "max6625", max6625, },
{ "max6626", max6626, }, { "max6626", max6626, },
{ "mcp980x", mcp980x, }, { "mcp980x", mcp980x, },
...@@ -409,6 +415,12 @@ static int lm75_detect(struct i2c_client *new_client, ...@@ -409,6 +415,12 @@ static int lm75_detect(struct i2c_client *new_client,
|| i2c_smbus_read_byte_data(new_client, 7) != os) || i2c_smbus_read_byte_data(new_client, 7) != os)
return -ENODEV; return -ENODEV;
} }
/*
* It is very unlikely that this is a LM75 if both
* hysteresis and temperature limit registers are 0.
*/
if (hyst == 0 && os == 0)
return -ENODEV;
/* Addresses cycling */ /* Addresses cycling */
for (i = 8; i <= 248; i += 40) { for (i = 8; i <= 248; i += 40) {
......
/* /*
* Driver for Texas Instruments / National Semiconductor LM95234 * Driver for Texas Instruments / National Semiconductor LM95234
* *
* Copyright (c) 2013 Guenter Roeck <linux@roeck-us.net> * Copyright (c) 2013, 2014 Guenter Roeck <linux@roeck-us.net>
* *
* Derived from lm95241.c * Derived from lm95241.c
* Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com> * Copyright (C) 2008, 2010 Davide Rizzo <elpa.rizzo@gmail.com>
...@@ -30,7 +30,10 @@ ...@@ -30,7 +30,10 @@
#define DRVNAME "lm95234" #define DRVNAME "lm95234"
static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END }; enum chips { lm95233, lm95234 };
static const unsigned short normal_i2c[] = {
0x18, 0x2a, 0x2b, 0x4d, 0x4e, I2C_CLIENT_END };
/* LM95234 registers */ /* LM95234 registers */
#define LM95234_REG_MAN_ID 0xFE #define LM95234_REG_MAN_ID 0xFE
...@@ -53,11 +56,13 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END }; ...@@ -53,11 +56,13 @@ static const unsigned short normal_i2c[] = { 0x18, 0x4d, 0x4e, I2C_CLIENT_END };
#define LM95234_REG_TCRIT_HYST 0x5a #define LM95234_REG_TCRIT_HYST 0x5a
#define NATSEMI_MAN_ID 0x01 #define NATSEMI_MAN_ID 0x01
#define LM95233_CHIP_ID 0x89
#define LM95234_CHIP_ID 0x79 #define LM95234_CHIP_ID 0x79
/* Client data (each client gets its own) */ /* Client data (each client gets its own) */
struct lm95234_data { struct lm95234_data {
struct i2c_client *client; struct i2c_client *client;
const struct attribute_group *groups[3];
struct mutex update_lock; struct mutex update_lock;
unsigned long last_updated, interval; /* in jiffies */ unsigned long last_updated, interval; /* in jiffies */
bool valid; /* false until following fields are valid */ bool valid; /* false until following fields are valid */
...@@ -564,35 +569,23 @@ static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset, ...@@ -564,35 +569,23 @@ static SENSOR_DEVICE_ATTR(temp5_offset, S_IWUSR | S_IRUGO, show_offset,
static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval, static DEVICE_ATTR(update_interval, S_IWUSR | S_IRUGO, show_interval,
set_interval); set_interval);
static struct attribute *lm95234_attrs[] = { static struct attribute *lm95234_common_attrs[] = {
&sensor_dev_attr_temp1_input.dev_attr.attr, &sensor_dev_attr_temp1_input.dev_attr.attr,
&sensor_dev_attr_temp2_input.dev_attr.attr, &sensor_dev_attr_temp2_input.dev_attr.attr,
&sensor_dev_attr_temp3_input.dev_attr.attr, &sensor_dev_attr_temp3_input.dev_attr.attr,
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp2_fault.dev_attr.attr, &sensor_dev_attr_temp2_fault.dev_attr.attr,
&sensor_dev_attr_temp3_fault.dev_attr.attr, &sensor_dev_attr_temp3_fault.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
&sensor_dev_attr_temp2_type.dev_attr.attr, &sensor_dev_attr_temp2_type.dev_attr.attr,
&sensor_dev_attr_temp3_type.dev_attr.attr, &sensor_dev_attr_temp3_type.dev_attr.attr,
&sensor_dev_attr_temp4_type.dev_attr.attr,
&sensor_dev_attr_temp5_type.dev_attr.attr,
&sensor_dev_attr_temp1_max.dev_attr.attr, &sensor_dev_attr_temp1_max.dev_attr.attr,
&sensor_dev_attr_temp2_max.dev_attr.attr, &sensor_dev_attr_temp2_max.dev_attr.attr,
&sensor_dev_attr_temp3_max.dev_attr.attr, &sensor_dev_attr_temp3_max.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp1_max_hyst.dev_attr.attr, &sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp2_max_hyst.dev_attr.attr, &sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp3_max_hyst.dev_attr.attr, &sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp1_max_alarm.dev_attr.attr, &sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_max_alarm.dev_attr.attr, &sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp3_max_alarm.dev_attr.attr, &sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_crit.dev_attr.attr, &sensor_dev_attr_temp2_crit.dev_attr.attr,
&sensor_dev_attr_temp3_crit.dev_attr.attr, &sensor_dev_attr_temp3_crit.dev_attr.attr,
&sensor_dev_attr_temp2_crit_hyst.dev_attr.attr, &sensor_dev_attr_temp2_crit_hyst.dev_attr.attr,
...@@ -601,18 +594,44 @@ static struct attribute *lm95234_attrs[] = { ...@@ -601,18 +594,44 @@ static struct attribute *lm95234_attrs[] = {
&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr, &sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
&sensor_dev_attr_temp2_offset.dev_attr.attr, &sensor_dev_attr_temp2_offset.dev_attr.attr,
&sensor_dev_attr_temp3_offset.dev_attr.attr, &sensor_dev_attr_temp3_offset.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL
};
static const struct attribute_group lm95234_common_group = {
.attrs = lm95234_common_attrs,
};
static struct attribute *lm95234_attrs[] = {
&sensor_dev_attr_temp4_input.dev_attr.attr,
&sensor_dev_attr_temp5_input.dev_attr.attr,
&sensor_dev_attr_temp4_fault.dev_attr.attr,
&sensor_dev_attr_temp5_fault.dev_attr.attr,
&sensor_dev_attr_temp4_type.dev_attr.attr,
&sensor_dev_attr_temp5_type.dev_attr.attr,
&sensor_dev_attr_temp4_max.dev_attr.attr,
&sensor_dev_attr_temp5_max.dev_attr.attr,
&sensor_dev_attr_temp4_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp5_max_hyst.dev_attr.attr,
&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
&sensor_dev_attr_temp4_offset.dev_attr.attr, &sensor_dev_attr_temp4_offset.dev_attr.attr,
&sensor_dev_attr_temp5_offset.dev_attr.attr, &sensor_dev_attr_temp5_offset.dev_attr.attr,
&dev_attr_update_interval.attr,
NULL NULL
}; };
ATTRIBUTE_GROUPS(lm95234);
static const struct attribute_group lm95234_group = {
.attrs = lm95234_attrs,
};
static int lm95234_detect(struct i2c_client *client, static int lm95234_detect(struct i2c_client *client,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = client->adapter; struct i2c_adapter *adapter = client->adapter;
int address = client->addr;
u8 config_mask, model_mask;
int mfg_id, chip_id, val; int mfg_id, chip_id, val;
const char *name;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
...@@ -622,15 +641,31 @@ static int lm95234_detect(struct i2c_client *client, ...@@ -622,15 +641,31 @@ static int lm95234_detect(struct i2c_client *client,
return -ENODEV; return -ENODEV;
chip_id = i2c_smbus_read_byte_data(client, LM95234_REG_CHIP_ID); chip_id = i2c_smbus_read_byte_data(client, LM95234_REG_CHIP_ID);
if (chip_id != LM95234_CHIP_ID) switch (chip_id) {
case LM95233_CHIP_ID:
if (address != 0x18 && address != 0x2a && address != 0x2b)
return -ENODEV;
config_mask = 0xbf;
model_mask = 0xf9;
name = "lm95233";
break;
case LM95234_CHIP_ID:
if (address != 0x18 && address != 0x4d && address != 0x4e)
return -ENODEV;
config_mask = 0xbc;
model_mask = 0xe1;
name = "lm95234";
break;
default:
return -ENODEV; return -ENODEV;
}
val = i2c_smbus_read_byte_data(client, LM95234_REG_STATUS); val = i2c_smbus_read_byte_data(client, LM95234_REG_STATUS);
if (val & 0x30) if (val & 0x30)
return -ENODEV; return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG); val = i2c_smbus_read_byte_data(client, LM95234_REG_CONFIG);
if (val & 0xbc) if (val & config_mask)
return -ENODEV; return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE); val = i2c_smbus_read_byte_data(client, LM95234_REG_CONVRATE);
...@@ -638,14 +673,14 @@ static int lm95234_detect(struct i2c_client *client, ...@@ -638,14 +673,14 @@ static int lm95234_detect(struct i2c_client *client,
return -ENODEV; return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL); val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL);
if (val & 0xe1) if (val & model_mask)
return -ENODEV; return -ENODEV;
val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS); val = i2c_smbus_read_byte_data(client, LM95234_REG_REM_MODEL_STS);
if (val & 0xe1) if (val & model_mask)
return -ENODEV; return -ENODEV;
strlcpy(info->type, "lm95234", I2C_NAME_SIZE); strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
} }
...@@ -698,15 +733,19 @@ static int lm95234_probe(struct i2c_client *client, ...@@ -698,15 +733,19 @@ static int lm95234_probe(struct i2c_client *client,
if (err < 0) if (err < 0)
return err; return err;
data->groups[0] = &lm95234_common_group;
if (id->driver_data == lm95234)
data->groups[1] = &lm95234_group;
hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name,
data, data, data->groups);
lm95234_groups);
return PTR_ERR_OR_ZERO(hwmon_dev); return PTR_ERR_OR_ZERO(hwmon_dev);
} }
/* Driver data (common to all clients) */ /* Driver data (common to all clients) */
static const struct i2c_device_id lm95234_id[] = { static const struct i2c_device_id lm95234_id[] = {
{ "lm95234", 0 }, { "lm95233", lm95233 },
{ "lm95234", lm95234 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, lm95234_id); MODULE_DEVICE_TABLE(i2c, lm95234_id);
...@@ -725,5 +764,5 @@ static struct i2c_driver lm95234_driver = { ...@@ -725,5 +764,5 @@ static struct i2c_driver lm95234_driver = {
module_i2c_driver(lm95234_driver); module_i2c_driver(lm95234_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>"); MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("LM95234 sensor driver"); MODULE_DESCRIPTION("LM95233/LM95234 sensor driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
/* /*
* Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com> * Copyright (C) 2011 Alexander Stein <alexander.stein@systec-electronic.com>
* *
* The LM95245 is a sensor chip made by National Semiconductors. * The LM95245 is a sensor chip made by TI / National Semiconductor.
* It reports up to two temperatures (its own plus an external one). * It reports up to two temperatures (its own plus an external one).
* Complete datasheet can be obtained from National's website at:
* http://www.national.com/ds.cgi/LM/LM95245.pdf
* *
* This driver is based on lm95241.c * This driver is based on lm95241.c
* *
...@@ -34,8 +32,6 @@ ...@@ -34,8 +32,6 @@
#include <linux/mutex.h> #include <linux/mutex.h>
#include <linux/sysfs.h> #include <linux/sysfs.h>
#define DEVNAME "lm95245"
static const unsigned short normal_i2c[] = { static const unsigned short normal_i2c[] = {
0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END }; 0x18, 0x19, 0x29, 0x4c, 0x4d, I2C_CLIENT_END };
...@@ -98,7 +94,8 @@ static const unsigned short normal_i2c[] = { ...@@ -98,7 +94,8 @@ static const unsigned short normal_i2c[] = {
#define STATUS1_LOC 0x01 #define STATUS1_LOC 0x01
#define MANUFACTURER_ID 0x01 #define MANUFACTURER_ID 0x01
#define DEFAULT_REVISION 0xB3 #define LM95235_REVISION 0xB1
#define LM95245_REVISION 0xB3
static const u8 lm95245_reg_address[] = { static const u8 lm95245_reg_address[] = {
LM95245_REG_R_LOCAL_TEMPH_S, LM95245_REG_R_LOCAL_TEMPH_S,
...@@ -427,17 +424,32 @@ static int lm95245_detect(struct i2c_client *new_client, ...@@ -427,17 +424,32 @@ static int lm95245_detect(struct i2c_client *new_client,
struct i2c_board_info *info) struct i2c_board_info *info)
{ {
struct i2c_adapter *adapter = new_client->adapter; struct i2c_adapter *adapter = new_client->adapter;
int address = new_client->addr;
const char *name;
int rev, id;
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -ENODEV; return -ENODEV;
if (i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID) id = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_MAN_ID);
!= MANUFACTURER_ID if (id != MANUFACTURER_ID)
|| i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID)
!= DEFAULT_REVISION)
return -ENODEV; return -ENODEV;
strlcpy(info->type, DEVNAME, I2C_NAME_SIZE); rev = i2c_smbus_read_byte_data(new_client, LM95245_REG_R_CHIP_ID);
switch (rev) {
case LM95235_REVISION:
if (address != 0x18 && address != 0x29 && address != 0x4c)
return -ENODEV;
name = "lm95235";
break;
case LM95245_REVISION:
name = "lm95245";
break;
default:
return -ENODEV;
}
strlcpy(info->type, name, I2C_NAME_SIZE);
return 0; return 0;
} }
...@@ -484,7 +496,8 @@ static int lm95245_probe(struct i2c_client *client, ...@@ -484,7 +496,8 @@ static int lm95245_probe(struct i2c_client *client,
/* Driver data (common to all clients) */ /* Driver data (common to all clients) */
static const struct i2c_device_id lm95245_id[] = { static const struct i2c_device_id lm95245_id[] = {
{ DEVNAME, 0 }, { "lm95235", 0 },
{ "lm95245", 0 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, lm95245_id); MODULE_DEVICE_TABLE(i2c, lm95245_id);
...@@ -492,7 +505,7 @@ MODULE_DEVICE_TABLE(i2c, lm95245_id); ...@@ -492,7 +505,7 @@ MODULE_DEVICE_TABLE(i2c, lm95245_id);
static struct i2c_driver lm95245_driver = { static struct i2c_driver lm95245_driver = {
.class = I2C_CLASS_HWMON, .class = I2C_CLASS_HWMON,
.driver = { .driver = {
.name = DEVNAME, .name = "lm95245",
}, },
.probe = lm95245_probe, .probe = lm95245_probe,
.id_table = lm95245_id, .id_table = lm95245_id,
...@@ -503,5 +516,5 @@ static struct i2c_driver lm95245_driver = { ...@@ -503,5 +516,5 @@ static struct i2c_driver lm95245_driver = {
module_i2c_driver(lm95245_driver); module_i2c_driver(lm95245_driver);
MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>"); MODULE_AUTHOR("Alexander Stein <alexander.stein@systec-electronic.com>");
MODULE_DESCRIPTION("LM95245 sensor driver"); MODULE_DESCRIPTION("LM95235/LM95245 sensor driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
This diff is collapsed.
This diff is collapsed.
...@@ -47,15 +47,22 @@ config SENSORS_LM25066 ...@@ -47,15 +47,22 @@ config SENSORS_LM25066
be called lm25066. be called lm25066.
config SENSORS_LTC2978 config SENSORS_LTC2978
tristate "Linear Technologies LTC2974, LTC2978, LTC3880, and LTC3883" tristate "Linear Technologies LTC2978 and compatibles"
default n default n
help help
If you say yes here you get hardware monitoring support for Linear If you say yes here you get hardware monitoring support for Linear
Technology LTC2974, LTC2978, LTC3880, and LTC3883. Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
This driver can also be built as a module. If so, the module will This driver can also be built as a module. If so, the module will
be called ltc2978. be called ltc2978.
config SENSORS_LTC2978_REGULATOR
boolean "Regulator support for LTC2978 and compatibles"
depends on SENSORS_LTC2978 && REGULATOR
help
If you say yes here you get regulator support for Linear
Technology LTC2974, LTC2977, LTC2978, LTC3880, LTC3883, and LTM4676.
config SENSORS_MAX16064 config SENSORS_MAX16064
tristate "Maxim MAX16064" tristate "Maxim MAX16064"
default n default n
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/regulator/driver.h>
#include "pmbus.h" #include "pmbus.h"
enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 }; enum chips { ltc2974, ltc2977, ltc2978, ltc3880, ltc3883, ltm4676 };
...@@ -374,6 +375,19 @@ static const struct i2c_device_id ltc2978_id[] = { ...@@ -374,6 +375,19 @@ static const struct i2c_device_id ltc2978_id[] = {
}; };
MODULE_DEVICE_TABLE(i2c, ltc2978_id); MODULE_DEVICE_TABLE(i2c, ltc2978_id);
#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
static const struct regulator_desc ltc2978_reg_desc[] = {
PMBUS_REGULATOR("vout", 0),
PMBUS_REGULATOR("vout", 1),
PMBUS_REGULATOR("vout", 2),
PMBUS_REGULATOR("vout", 3),
PMBUS_REGULATOR("vout", 4),
PMBUS_REGULATOR("vout", 5),
PMBUS_REGULATOR("vout", 6),
PMBUS_REGULATOR("vout", 7),
};
#endif /* CONFIG_SENSORS_LTC2978_REGULATOR */
static int ltc2978_probe(struct i2c_client *client, static int ltc2978_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
...@@ -487,13 +501,36 @@ static int ltc2978_probe(struct i2c_client *client, ...@@ -487,13 +501,36 @@ static int ltc2978_probe(struct i2c_client *client,
default: default:
return -ENODEV; return -ENODEV;
} }
#if IS_ENABLED(CONFIG_SENSORS_LTC2978_REGULATOR)
info->num_regulators = info->pages;
info->reg_desc = ltc2978_reg_desc;
if (info->num_regulators > ARRAY_SIZE(ltc2978_reg_desc)) {
dev_err(&client->dev, "num_regulators too large!");
info->num_regulators = ARRAY_SIZE(ltc2978_reg_desc);
}
#endif
return pmbus_do_probe(client, id, info); return pmbus_do_probe(client, id, info);
} }
/* This is the driver that will be inserted */ #ifdef CONFIG_OF
static const struct of_device_id ltc2978_of_match[] = {
{ .compatible = "lltc,ltc2974" },
{ .compatible = "lltc,ltc2977" },
{ .compatible = "lltc,ltc2978" },
{ .compatible = "lltc,ltc3880" },
{ .compatible = "lltc,ltc3883" },
{ .compatible = "lltc,ltm4676" },
{ }
};
MODULE_DEVICE_TABLE(of, ltc2978_of_match);
#endif
static struct i2c_driver ltc2978_driver = { static struct i2c_driver ltc2978_driver = {
.driver = { .driver = {
.name = "ltc2978", .name = "ltc2978",
.of_match_table = of_match_ptr(ltc2978_of_match),
}, },
.probe = ltc2978_probe, .probe = ltc2978_probe,
.remove = pmbus_do_remove, .remove = pmbus_do_remove,
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/regulator/driver.h>
#ifndef PMBUS_H #ifndef PMBUS_H
#define PMBUS_H #define PMBUS_H
...@@ -185,6 +187,11 @@ ...@@ -185,6 +187,11 @@
#define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34) #define PMBUS_VIRT_VMON_OV_FAULT_LIMIT (PMBUS_VIRT_BASE + 34)
#define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35) #define PMBUS_VIRT_STATUS_VMON (PMBUS_VIRT_BASE + 35)
/*
* OPERATION
*/
#define PB_OPERATION_CONTROL_ON (1<<7)
/* /*
* CAPABILITY * CAPABILITY
*/ */
...@@ -365,8 +372,27 @@ struct pmbus_driver_info { ...@@ -365,8 +372,27 @@ struct pmbus_driver_info {
*/ */
int (*identify)(struct i2c_client *client, int (*identify)(struct i2c_client *client,
struct pmbus_driver_info *info); struct pmbus_driver_info *info);
/* Regulator functionality, if supported by this chip driver. */
int num_regulators;
const struct regulator_desc *reg_desc;
}; };
/* Regulator ops */
extern struct regulator_ops pmbus_regulator_ops;
/* Macro for filling in array of struct regulator_desc */
#define PMBUS_REGULATOR(_name, _id) \
[_id] = { \
.name = (_name # _id), \
.id = (_id), \
.of_match = of_match_ptr(_name # _id), \
.regulators_node = of_match_ptr("regulators"), \
.ops = &pmbus_regulator_ops, \
.owner = THIS_MODULE, \
}
/* Function declarations */ /* Function declarations */
void pmbus_clear_cache(struct i2c_client *client); void pmbus_clear_cache(struct i2c_client *client);
...@@ -375,6 +401,10 @@ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg); ...@@ -375,6 +401,10 @@ int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word); int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg, u16 word);
int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg); int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg);
int pmbus_write_byte(struct i2c_client *client, int page, u8 value); int pmbus_write_byte(struct i2c_client *client, int page, u8 value);
int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg,
u8 value);
int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
u8 mask, u8 value);
void pmbus_clear_faults(struct i2c_client *client); void pmbus_clear_faults(struct i2c_client *client);
bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg); bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg); bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
......
...@@ -29,6 +29,8 @@ ...@@ -29,6 +29,8 @@
#include <linux/hwmon-sysfs.h> #include <linux/hwmon-sysfs.h>
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <linux/i2c/pmbus.h> #include <linux/i2c/pmbus.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include "pmbus.h" #include "pmbus.h"
/* /*
...@@ -253,6 +255,37 @@ int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg) ...@@ -253,6 +255,37 @@ int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
} }
EXPORT_SYMBOL_GPL(pmbus_read_byte_data); EXPORT_SYMBOL_GPL(pmbus_read_byte_data);
int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, u8 value)
{
int rv;
rv = pmbus_set_page(client, page);
if (rv < 0)
return rv;
return i2c_smbus_write_byte_data(client, reg, value);
}
EXPORT_SYMBOL_GPL(pmbus_write_byte_data);
int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
u8 mask, u8 value)
{
unsigned int tmp;
int rv;
rv = pmbus_read_byte_data(client, page, reg);
if (rv < 0)
return rv;
tmp = (rv & ~mask) | (value & mask);
if (tmp != rv)
rv = pmbus_write_byte_data(client, page, reg, tmp);
return rv;
}
EXPORT_SYMBOL_GPL(pmbus_update_byte_data);
/* /*
* _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if * _pmbus_read_byte_data() is similar to pmbus_read_byte_data(), but checks if
* a device specific mapping function exists and calls it if necessary. * a device specific mapping function exists and calls it if necessary.
...@@ -1727,6 +1760,84 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data, ...@@ -1727,6 +1760,84 @@ static int pmbus_init_common(struct i2c_client *client, struct pmbus_data *data,
return 0; return 0;
} }
#if IS_ENABLED(CONFIG_REGULATOR)
static int pmbus_regulator_is_enabled(struct regulator_dev *rdev)
{
struct device *dev = rdev_get_dev(rdev);
struct i2c_client *client = to_i2c_client(dev->parent);
u8 page = rdev_get_id(rdev);
int ret;
ret = pmbus_read_byte_data(client, page, PMBUS_OPERATION);
if (ret < 0)
return ret;
return !!(ret & PB_OPERATION_CONTROL_ON);
}
static int _pmbus_regulator_on_off(struct regulator_dev *rdev, bool enable)
{
struct device *dev = rdev_get_dev(rdev);
struct i2c_client *client = to_i2c_client(dev->parent);
u8 page = rdev_get_id(rdev);
return pmbus_update_byte_data(client, page, PMBUS_OPERATION,
PB_OPERATION_CONTROL_ON,
enable ? PB_OPERATION_CONTROL_ON : 0);
}
static int pmbus_regulator_enable(struct regulator_dev *rdev)
{
return _pmbus_regulator_on_off(rdev, 1);
}
static int pmbus_regulator_disable(struct regulator_dev *rdev)
{
return _pmbus_regulator_on_off(rdev, 0);
}
struct regulator_ops pmbus_regulator_ops = {
.enable = pmbus_regulator_enable,
.disable = pmbus_regulator_disable,
.is_enabled = pmbus_regulator_is_enabled,
};
EXPORT_SYMBOL_GPL(pmbus_regulator_ops);
static int pmbus_regulator_register(struct pmbus_data *data)
{
struct device *dev = data->dev;
const struct pmbus_driver_info *info = data->info;
const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
struct regulator_dev *rdev;
int i;
for (i = 0; i < info->num_regulators; i++) {
struct regulator_config config = { };
config.dev = dev;
config.driver_data = data;
if (pdata && pdata->reg_init_data)
config.init_data = &pdata->reg_init_data[i];
rdev = devm_regulator_register(dev, &info->reg_desc[i],
&config);
if (IS_ERR(rdev)) {
dev_err(dev, "Failed to register %s regulator\n",
info->reg_desc[i].name);
return PTR_ERR(rdev);
}
}
return 0;
}
#else
static int pmbus_regulator_register(struct pmbus_data *data)
{
return 0;
}
#endif
int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
struct pmbus_driver_info *info) struct pmbus_driver_info *info)
{ {
...@@ -1781,8 +1892,15 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id, ...@@ -1781,8 +1892,15 @@ int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
dev_err(dev, "Failed to register hwmon device\n"); dev_err(dev, "Failed to register hwmon device\n");
goto out_kfree; goto out_kfree;
} }
ret = pmbus_regulator_register(data);
if (ret)
goto out_unregister;
return 0; return 0;
out_unregister:
hwmon_device_unregister(data->hwmon_dev);
out_kfree: out_kfree:
kfree(data->group.attrs); kfree(data->group.attrs);
return ret; return ret;
......
...@@ -44,9 +44,10 @@ ...@@ -44,9 +44,10 @@
#include <linux/sysfs.h> #include <linux/sysfs.h>
/* Addresses to scan */ /* Addresses to scan */
static const unsigned short normal_i2c[] = { 0x4c, 0x4d, 0x4e, I2C_CLIENT_END }; static const unsigned short normal_i2c[] = { 0x37, 0x48, 0x49, 0x4a, 0x4c, 0x4d,
0x4e, 0x4f, I2C_CLIENT_END };
enum chips { tmp401, tmp411, tmp431, tmp432 }; enum chips { tmp401, tmp411, tmp431, tmp432, tmp435 };
/* /*
* The TMP401 registers, note some registers have different addresses for * The TMP401 registers, note some registers have different addresses for
...@@ -136,6 +137,7 @@ static const u8 TMP432_STATUS_REG[] = { ...@@ -136,6 +137,7 @@ static const u8 TMP432_STATUS_REG[] = {
#define TMP411C_DEVICE_ID 0x10 #define TMP411C_DEVICE_ID 0x10
#define TMP431_DEVICE_ID 0x31 #define TMP431_DEVICE_ID 0x31
#define TMP432_DEVICE_ID 0x32 #define TMP432_DEVICE_ID 0x32
#define TMP435_DEVICE_ID 0x35
/* /*
* Driver data (common to all clients) * Driver data (common to all clients)
...@@ -146,6 +148,7 @@ static const struct i2c_device_id tmp401_id[] = { ...@@ -146,6 +148,7 @@ static const struct i2c_device_id tmp401_id[] = {
{ "tmp411", tmp411 }, { "tmp411", tmp411 },
{ "tmp431", tmp431 }, { "tmp431", tmp431 },
{ "tmp432", tmp432 }, { "tmp432", tmp432 },
{ "tmp435", tmp435 },
{ } { }
}; };
MODULE_DEVICE_TABLE(i2c, tmp401_id); MODULE_DEVICE_TABLE(i2c, tmp401_id);
...@@ -613,10 +616,10 @@ static const struct attribute_group tmp432_group = { ...@@ -613,10 +616,10 @@ static const struct attribute_group tmp432_group = {
* Begin non sysfs callback code (aka Real code) * Begin non sysfs callback code (aka Real code)
*/ */
static void tmp401_init_client(struct tmp401_data *data, static int tmp401_init_client(struct tmp401_data *data,
struct i2c_client *client) struct i2c_client *client)
{ {
int config, config_orig; int config, config_orig, status = 0;
/* Set the conversion rate to 2 Hz */ /* Set the conversion rate to 2 Hz */
i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5); i2c_smbus_write_byte_data(client, TMP401_CONVERSION_RATE_WRITE, 5);
...@@ -624,16 +627,18 @@ static void tmp401_init_client(struct tmp401_data *data, ...@@ -624,16 +627,18 @@ static void tmp401_init_client(struct tmp401_data *data,
/* Start conversions (disable shutdown if necessary) */ /* Start conversions (disable shutdown if necessary) */
config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ); config = i2c_smbus_read_byte_data(client, TMP401_CONFIG_READ);
if (config < 0) { if (config < 0)
dev_warn(&client->dev, "Initialization failed!\n"); return config;
return;
}
config_orig = config; config_orig = config;
config &= ~TMP401_CONFIG_SHUTDOWN; config &= ~TMP401_CONFIG_SHUTDOWN;
if (config != config_orig) if (config != config_orig)
i2c_smbus_write_byte_data(client, TMP401_CONFIG_WRITE, config); status = i2c_smbus_write_byte_data(client,
TMP401_CONFIG_WRITE,
config);
return status;
} }
static int tmp401_detect(struct i2c_client *client, static int tmp401_detect(struct i2c_client *client,
...@@ -675,15 +680,18 @@ static int tmp401_detect(struct i2c_client *client, ...@@ -675,15 +680,18 @@ static int tmp401_detect(struct i2c_client *client,
kind = tmp411; kind = tmp411;
break; break;
case TMP431_DEVICE_ID: case TMP431_DEVICE_ID:
if (client->addr == 0x4e) if (client->addr != 0x4c && client->addr != 0x4d)
return -ENODEV; return -ENODEV;
kind = tmp431; kind = tmp431;
break; break;
case TMP432_DEVICE_ID: case TMP432_DEVICE_ID:
if (client->addr == 0x4e) if (client->addr != 0x4c && client->addr != 0x4d)
return -ENODEV; return -ENODEV;
kind = tmp432; kind = tmp432;
break; break;
case TMP435_DEVICE_ID:
kind = tmp435;
break;
default: default:
return -ENODEV; return -ENODEV;
} }
...@@ -705,11 +713,13 @@ static int tmp401_detect(struct i2c_client *client, ...@@ -705,11 +713,13 @@ static int tmp401_detect(struct i2c_client *client,
static int tmp401_probe(struct i2c_client *client, static int tmp401_probe(struct i2c_client *client,
const struct i2c_device_id *id) const struct i2c_device_id *id)
{ {
const char *names[] = { "TMP401", "TMP411", "TMP431", "TMP432" }; static const char * const names[] = {
"TMP401", "TMP411", "TMP431", "TMP432", "TMP435"
};
struct device *dev = &client->dev; struct device *dev = &client->dev;
struct device *hwmon_dev; struct device *hwmon_dev;
struct tmp401_data *data; struct tmp401_data *data;
int groups = 0; int groups = 0, status;
data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL); data = devm_kzalloc(dev, sizeof(struct tmp401_data), GFP_KERNEL);
if (!data) if (!data)
...@@ -720,7 +730,9 @@ static int tmp401_probe(struct i2c_client *client, ...@@ -720,7 +730,9 @@ static int tmp401_probe(struct i2c_client *client,
data->kind = id->driver_data; data->kind = id->driver_data;
/* Initialize the TMP401 chip */ /* Initialize the TMP401 chip */
tmp401_init_client(data, client); status = tmp401_init_client(data, client);
if (status < 0)
return status;
/* Register sysfs hooks */ /* Register sysfs hooks */
data->groups[groups++] = &tmp401_group; data->groups[groups++] = &tmp401_group;
......
...@@ -40,6 +40,10 @@ ...@@ -40,6 +40,10 @@
struct pmbus_platform_data { struct pmbus_platform_data {
u32 flags; /* Device specific flags */ u32 flags; /* Device specific flags */
/* regulator support */
int num_regulators;
struct regulator_init_data *reg_init_data;
}; };
#endif /* _PMBUS_H_ */ #endif /* _PMBUS_H_ */
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