diff options
Diffstat (limited to 'drivers/hwmon/ds1621.c')
-rw-r--r-- | drivers/hwmon/ds1621.c | 102 |
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 */ | 56 | static 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) \ | 139 | static ssize_t show_temp(struct device *dev, struct device_attribute *da, |
137 | static 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 | ||
143 | show(temp); | 148 | static ssize_t set_temp(struct device *dev, struct device_attribute *da, |
144 | show(temp_min); | 149 | const char *buf, size_t count) |
145 | show(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); |
148 | static 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 | ||
162 | set_temp(min, temp_min, DS1621_REG_TEMP_MIN); | 156 | mutex_lock(&data->update_lock); |
163 | set_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 | ||
165 | static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf) | 164 | static 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 | ||
171 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 171 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
172 | static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL); | 172 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0); |
173 | static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min); | 173 | static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1); |
174 | static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max); | 174 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2); |
175 | 175 | ||
176 | static struct attribute *ds1621_attributes[] = { | 176 | static 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, |