summaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/adt7411.c
diff options
context:
space:
mode:
authorMichael Walle <michael@walle.cc>2016-07-25 05:12:06 -0400
committerGuenter Roeck <linux@roeck-us.net>2016-09-09 00:34:14 -0400
commita95da110cd6f464e7ea413224add0700051fe9ac (patch)
tree08b0ddfc859c398fa5d179c9be2a363a27545baa /drivers/hwmon/adt7411.c
parent637ab157d4a94145a6c9b89113222b6c80fab54c (diff)
hwmon: (adt7411) add external thermal diode support
If the EXT_TDM bit is set, the chip supports a second temperature sensor instead of two voltage sensors. Signed-off-by: Michael Walle <michael@walle.cc> Signed-off-by: Guenter Roeck <linux@roeck-us.net>
Diffstat (limited to 'drivers/hwmon/adt7411.c')
-rw-r--r--drivers/hwmon/adt7411.c51
1 files changed, 43 insertions, 8 deletions
diff --git a/drivers/hwmon/adt7411.c b/drivers/hwmon/adt7411.c
index fc1e65a263a4..812fbc00f693 100644
--- a/drivers/hwmon/adt7411.c
+++ b/drivers/hwmon/adt7411.c
@@ -7,8 +7,7 @@
7 * it under the terms of the GNU General Public License version 2 as 7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation. 8 * published by the Free Software Foundation.
9 * 9 *
10 * TODO: SPI, support for external temperature sensor 10 * TODO: SPI, use power-down mode for suspend?, interrupt handling?
11 * use power-down mode for suspend?, interrupt handling?
12 */ 11 */
13 12
14#include <linux/kernel.h> 13#include <linux/kernel.h>
@@ -31,6 +30,7 @@
31#define ADT7411_REG_CFG1 0x18 30#define ADT7411_REG_CFG1 0x18
32#define ADT7411_CFG1_START_MONITOR (1 << 0) 31#define ADT7411_CFG1_START_MONITOR (1 << 0)
33#define ADT7411_CFG1_RESERVED_BIT1 (1 << 1) 32#define ADT7411_CFG1_RESERVED_BIT1 (1 << 1)
33#define ADT7411_CFG1_EXT_TDM (1 << 2)
34#define ADT7411_CFG1_RESERVED_BIT3 (1 << 3) 34#define ADT7411_CFG1_RESERVED_BIT3 (1 << 3)
35 35
36#define ADT7411_REG_CFG2 0x19 36#define ADT7411_REG_CFG2 0x19
@@ -57,6 +57,7 @@ struct adt7411_data {
57 unsigned long next_update; 57 unsigned long next_update;
58 int vref_cached; 58 int vref_cached;
59 struct i2c_client *client; 59 struct i2c_client *client;
60 bool use_ext_temp;
60}; 61};
61 62
62/* 63/*
@@ -127,11 +128,20 @@ static ssize_t adt7411_show_vdd(struct device *dev,
127static ssize_t adt7411_show_temp(struct device *dev, 128static ssize_t adt7411_show_temp(struct device *dev,
128 struct device_attribute *attr, char *buf) 129 struct device_attribute *attr, char *buf)
129{ 130{
131 int nr = to_sensor_dev_attr(attr)->index;
130 struct adt7411_data *data = dev_get_drvdata(dev); 132 struct adt7411_data *data = dev_get_drvdata(dev);
131 struct i2c_client *client = data->client; 133 struct i2c_client *client = data->client;
132 int val = adt7411_read_10_bit(client, ADT7411_REG_INT_TEMP_VDD_LSB, 134 int val;
133 ADT7411_REG_INT_TEMP_MSB, 0); 135 struct {
134 136 u8 low;
137 u8 high;
138 } reg[2] = {
139 { ADT7411_REG_INT_TEMP_VDD_LSB, ADT7411_REG_INT_TEMP_MSB },
140 { ADT7411_REG_EXT_TEMP_AIN14_LSB,
141 ADT7411_REG_EXT_TEMP_AIN1_MSB },
142 };
143
144 val = adt7411_read_10_bit(client, reg[nr].low, reg[nr].high, 0);
135 if (val < 0) 145 if (val < 0)
136 return val; 146 return val;
137 147
@@ -218,11 +228,13 @@ static ssize_t adt7411_set_bit(struct device *dev,
218 return ret < 0 ? ret : count; 228 return ret < 0 ? ret : count;
219} 229}
220 230
231
221#define ADT7411_BIT_ATTR(__name, __reg, __bit) \ 232#define ADT7411_BIT_ATTR(__name, __reg, __bit) \
222 SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \ 233 SENSOR_DEVICE_ATTR_2(__name, S_IRUGO | S_IWUSR, adt7411_show_bit, \
223 adt7411_set_bit, __bit, __reg) 234 adt7411_set_bit, __bit, __reg)
224 235
225static DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL); 236static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, adt7411_show_temp, NULL, 0);
237static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, adt7411_show_temp, NULL, 1);
226static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL); 238static DEVICE_ATTR(in0_input, S_IRUGO, adt7411_show_vdd, NULL);
227static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0); 239static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, adt7411_show_input, NULL, 0);
228static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1); 240static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, adt7411_show_input, NULL, 1);
@@ -237,7 +249,8 @@ static ADT7411_BIT_ATTR(fast_sampling, ADT7411_REG_CFG3, ADT7411_CFG3_ADC_CLK_22
237static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD); 249static ADT7411_BIT_ATTR(adc_ref_vdd, ADT7411_REG_CFG3, ADT7411_CFG3_REF_VDD);
238 250
239static struct attribute *adt7411_attrs[] = { 251static struct attribute *adt7411_attrs[] = {
240 &dev_attr_temp1_input.attr, 252 &sensor_dev_attr_temp1_input.dev_attr.attr,
253 &sensor_dev_attr_temp2_input.dev_attr.attr,
241 &dev_attr_in0_input.attr, 254 &dev_attr_in0_input.attr,
242 &sensor_dev_attr_in1_input.dev_attr.attr, 255 &sensor_dev_attr_in1_input.dev_attr.attr,
243 &sensor_dev_attr_in2_input.dev_attr.attr, 256 &sensor_dev_attr_in2_input.dev_attr.attr,
@@ -253,7 +266,27 @@ static struct attribute *adt7411_attrs[] = {
253 NULL 266 NULL
254}; 267};
255 268
256ATTRIBUTE_GROUPS(adt7411); 269static umode_t adt7411_attrs_visible(struct kobject *kobj,
270 struct attribute *attr, int index)
271{
272 struct device *dev = container_of(kobj, struct device, kobj);
273 struct adt7411_data *data = dev_get_drvdata(dev);
274 bool visible = true;
275
276 if (attr == &sensor_dev_attr_temp2_input.dev_attr.attr)
277 visible = data->use_ext_temp;
278 else if (attr == &sensor_dev_attr_in1_input.dev_attr.attr ||
279 attr == &sensor_dev_attr_in2_input.dev_attr.attr)
280 visible = !data->use_ext_temp;
281
282 return visible ? attr->mode : 0;
283}
284
285static const struct attribute_group adt7411_group = {
286 .attrs = adt7411_attrs,
287 .is_visible = adt7411_attrs_visible,
288};
289__ATTRIBUTE_GROUPS(adt7411);
257 290
258static int adt7411_detect(struct i2c_client *client, 291static int adt7411_detect(struct i2c_client *client,
259 struct i2c_board_info *info) 292 struct i2c_board_info *info)
@@ -309,6 +342,8 @@ static int adt7411_init_device(struct adt7411_data *data)
309 if (ret < 0) 342 if (ret < 0)
310 return ret; 343 return ret;
311 344
345 data->use_ext_temp = ret & ADT7411_CFG1_EXT_TDM;
346
312 /* 347 /*
313 * We must only write zero to bit 1 and only one to bit 3 according to 348 * We must only write zero to bit 1 and only one to bit 3 according to
314 * the datasheet. 349 * the datasheet.