aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/ds1621.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/ds1621.c')
-rw-r--r--drivers/hwmon/ds1621.c102
1 files changed, 48 insertions, 54 deletions
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index ccf0fe617e5f..7ac156a1603e 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -27,6 +27,7 @@
27#include <linux/jiffies.h> 27#include <linux/jiffies.h>
28#include <linux/i2c.h> 28#include <linux/i2c.h>
29#include <linux/hwmon.h> 29#include <linux/hwmon.h>
30#include <linux/hwmon-sysfs.h>
30#include <linux/err.h> 31#include <linux/err.h>
31#include <linux/mutex.h> 32#include <linux/mutex.h>
32#include <linux/sysfs.h> 33#include <linux/sysfs.h>
@@ -52,9 +53,11 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
52#define DS1621_REG_CONFIG_DONE 0x80 53#define DS1621_REG_CONFIG_DONE 0x80
53 54
54/* The DS1621 registers */ 55/* The DS1621 registers */
55#define DS1621_REG_TEMP 0xAA /* word, RO */ 56static const u8 DS1621_REG_TEMP[3] = {
56#define DS1621_REG_TEMP_MIN 0xA2 /* word, RW */ 57 0xAA, /* input, word, RO */
57#define DS1621_REG_TEMP_MAX 0xA1 /* word, RW */ 58 0xA2, /* min, word, RW */
59 0xA1, /* max, word, RW */
60};
58#define DS1621_REG_CONF 0xAC /* byte, RW */ 61#define DS1621_REG_CONF 0xAC /* byte, RW */
59#define DS1621_COM_START 0xEE /* no data */ 62#define DS1621_COM_START 0xEE /* no data */
60#define DS1621_COM_STOP 0x22 /* no data */ 63#define DS1621_COM_STOP 0x22 /* no data */
@@ -75,7 +78,7 @@ struct ds1621_data {
75 char valid; /* !=0 if following fields are valid */ 78 char valid; /* !=0 if following fields are valid */
76 unsigned long last_updated; /* In jiffies */ 79 unsigned long last_updated; /* In jiffies */
77 80
78 u16 temp, temp_min, temp_max; /* Register values, word */ 81 u16 temp[3]; /* Register values, word */
79 u8 conf; /* Register encoding, combined */ 82 u8 conf; /* Register encoding, combined */
80}; 83};
81 84
@@ -133,50 +136,47 @@ static void ds1621_init_client(struct i2c_client *client)
133 i2c_smbus_write_byte(client, DS1621_COM_START); 136 i2c_smbus_write_byte(client, DS1621_COM_START);
134} 137}
135 138
136#define show(value) \ 139static ssize_t show_temp(struct device *dev, struct device_attribute *da,
137static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf) \ 140 char *buf)
138{ \ 141{
139 struct ds1621_data *data = ds1621_update_client(dev); \ 142 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
140 return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value)); \ 143 struct ds1621_data *data = ds1621_update_client(dev);
144 return sprintf(buf, "%d\n",
145 LM75_TEMP_FROM_REG(data->temp[attr->index]));
141} 146}
142 147
143show(temp); 148static ssize_t set_temp(struct device *dev, struct device_attribute *da,
144show(temp_min); 149 const char *buf, size_t count)
145show(temp_max); 150{
146 151 struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
147#define set_temp(suffix, value, reg) \ 152 struct i2c_client *client = to_i2c_client(dev);
148static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf, \ 153 struct ds1621_data *data = ds1621_update_client(dev);
149 size_t count) \ 154 u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10));
150{ \
151 struct i2c_client *client = to_i2c_client(dev); \
152 struct ds1621_data *data = ds1621_update_client(dev); \
153 u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10)); \
154 \
155 mutex_lock(&data->update_lock); \
156 data->value = val; \
157 ds1621_write_value(client, reg, data->value); \
158 mutex_unlock(&data->update_lock); \
159 return count; \
160}
161 155
162set_temp(min, temp_min, DS1621_REG_TEMP_MIN); 156 mutex_lock(&data->update_lock);
163set_temp(max, temp_max, DS1621_REG_TEMP_MAX); 157 data->temp[attr->index] = val;
158 ds1621_write_value(client, DS1621_REG_TEMP[attr->index],
159 data->temp[attr->index]);
160 mutex_unlock(&data->update_lock);
161 return count;
162}
164 163
165static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) 164static ssize_t show_alarms(struct device *dev, struct device_attribute *da,
165 char *buf)
166{ 166{
167 struct ds1621_data *data = ds1621_update_client(dev); 167 struct ds1621_data *data = ds1621_update_client(dev);
168 return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf)); 168 return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf));
169} 169}
170 170
171static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); 171static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
172static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL); 172static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
173static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min); 173static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1);
174static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); 174static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2);
175 175
176static struct attribute *ds1621_attributes[] = { 176static struct attribute *ds1621_attributes[] = {
177 &dev_attr_temp1_input.attr, 177 &sensor_dev_attr_temp1_input.dev_attr.attr,
178 &dev_attr_temp1_min.attr, 178 &sensor_dev_attr_temp1_min.dev_attr.attr,
179 &dev_attr_temp1_max.attr, 179 &sensor_dev_attr_temp1_max.dev_attr.attr,
180 &dev_attr_alarms.attr, 180 &dev_attr_alarms.attr,
181 NULL 181 NULL
182}; 182};
@@ -200,7 +200,7 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
200 int conf, temp; 200 int conf, temp;
201 struct i2c_client *client; 201 struct i2c_client *client;
202 struct ds1621_data *data; 202 struct ds1621_data *data;
203 int err = 0; 203 int i, err = 0;
204 204
205 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 205 if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA
206 | I2C_FUNC_SMBUS_WORD_DATA 206 | I2C_FUNC_SMBUS_WORD_DATA
@@ -230,15 +230,11 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
230 if (conf & DS1621_REG_CONFIG_NVB) 230 if (conf & DS1621_REG_CONFIG_NVB)
231 goto exit_free; 231 goto exit_free;
232 /* The 7 lowest bits of a temperature should always be 0. */ 232 /* The 7 lowest bits of a temperature should always be 0. */
233 temp = ds1621_read_value(client, DS1621_REG_TEMP); 233 for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
234 if (temp & 0x007f) 234 temp = ds1621_read_value(client, DS1621_REG_TEMP[i]);
235 goto exit_free; 235 if (temp & 0x007f)
236 temp = ds1621_read_value(client, DS1621_REG_TEMP_MIN); 236 goto exit_free;
237 if (temp & 0x007f) 237 }
238 goto exit_free;
239 temp = ds1621_read_value(client, DS1621_REG_TEMP_MAX);
240 if (temp & 0x007f)
241 goto exit_free;
242 } 238 }
243 239
244 /* Fill in remaining client fields and put it into the global list */ 240 /* Fill in remaining client fields and put it into the global list */
@@ -301,23 +297,21 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
301 297
302 if (time_after(jiffies, data->last_updated + HZ + HZ / 2) 298 if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
303 || !data->valid) { 299 || !data->valid) {
300 int i;
304 301
305 dev_dbg(&client->dev, "Starting ds1621 update\n"); 302 dev_dbg(&client->dev, "Starting ds1621 update\n");
306 303
307 data->conf = ds1621_read_value(client, DS1621_REG_CONF); 304 data->conf = ds1621_read_value(client, DS1621_REG_CONF);
308 305
309 data->temp = ds1621_read_value(client, DS1621_REG_TEMP); 306 for (i = 0; i < ARRAY_SIZE(data->temp); i++)
310 307 data->temp[i] = ds1621_read_value(client,
311 data->temp_min = ds1621_read_value(client, 308 DS1621_REG_TEMP[i]);
312 DS1621_REG_TEMP_MIN);
313 data->temp_max = ds1621_read_value(client,
314 DS1621_REG_TEMP_MAX);
315 309
316 /* reset alarms if necessary */ 310 /* reset alarms if necessary */
317 new_conf = data->conf; 311 new_conf = data->conf;
318 if (data->temp > data->temp_min) 312 if (data->temp[0] > data->temp[1]) /* input > min */
319 new_conf &= ~DS1621_ALARM_TEMP_LOW; 313 new_conf &= ~DS1621_ALARM_TEMP_LOW;
320 if (data->temp < data->temp_max) 314 if (data->temp[0] < data->temp[2]) /* input < max */
321 new_conf &= ~DS1621_ALARM_TEMP_HIGH; 315 new_conf &= ~DS1621_ALARM_TEMP_HIGH;
322 if (data->conf != new_conf) 316 if (data->conf != new_conf)
323 ds1621_write_value(client, DS1621_REG_CONF, 317 ds1621_write_value(client, DS1621_REG_CONF,