diff options
Diffstat (limited to 'drivers/hwmon/adt7470.c')
-rw-r--r-- | drivers/hwmon/adt7470.c | 156 |
1 files changed, 134 insertions, 22 deletions
diff --git a/drivers/hwmon/adt7470.c b/drivers/hwmon/adt7470.c index ab8d5ebc9f75..633e1a1e9d79 100644 --- a/drivers/hwmon/adt7470.c +++ b/drivers/hwmon/adt7470.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/log2.h> | 30 | #include <linux/log2.h> |
31 | #include <linux/kthread.h> | ||
31 | 32 | ||
32 | /* Addresses to scan */ | 33 | /* Addresses to scan */ |
33 | static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; | 34 | static const unsigned short normal_i2c[] = { 0x2C, 0x2E, 0x2F, I2C_CLIENT_END }; |
@@ -132,6 +133,9 @@ I2C_CLIENT_INSMOD_1(adt7470); | |||
132 | /* Wait at least 200ms per sensor for 10 sensors */ | 133 | /* Wait at least 200ms per sensor for 10 sensors */ |
133 | #define TEMP_COLLECTION_TIME 2000 | 134 | #define TEMP_COLLECTION_TIME 2000 |
134 | 135 | ||
136 | /* auto update thing won't fire more than every 2s */ | ||
137 | #define AUTO_UPDATE_INTERVAL 2000 | ||
138 | |||
135 | /* datasheet says to divide this number by the fan reading to get fan rpm */ | 139 | /* datasheet says to divide this number by the fan reading to get fan rpm */ |
136 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | 140 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) |
137 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | 141 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM |
@@ -148,6 +152,7 @@ struct adt7470_data { | |||
148 | unsigned long limits_last_updated; /* In jiffies */ | 152 | unsigned long limits_last_updated; /* In jiffies */ |
149 | 153 | ||
150 | int num_temp_sensors; /* -1 = probe */ | 154 | int num_temp_sensors; /* -1 = probe */ |
155 | int temperatures_probed; | ||
151 | 156 | ||
152 | s8 temp[ADT7470_TEMP_COUNT]; | 157 | s8 temp[ADT7470_TEMP_COUNT]; |
153 | s8 temp_min[ADT7470_TEMP_COUNT]; | 158 | s8 temp_min[ADT7470_TEMP_COUNT]; |
@@ -164,6 +169,10 @@ struct adt7470_data { | |||
164 | u8 pwm_min[ADT7470_PWM_COUNT]; | 169 | u8 pwm_min[ADT7470_PWM_COUNT]; |
165 | s8 pwm_tmin[ADT7470_PWM_COUNT]; | 170 | s8 pwm_tmin[ADT7470_PWM_COUNT]; |
166 | u8 pwm_auto_temp[ADT7470_PWM_COUNT]; | 171 | u8 pwm_auto_temp[ADT7470_PWM_COUNT]; |
172 | |||
173 | struct task_struct *auto_update; | ||
174 | struct completion auto_update_stop; | ||
175 | unsigned int auto_update_interval; | ||
167 | }; | 176 | }; |
168 | 177 | ||
169 | static int adt7470_probe(struct i2c_client *client, | 178 | static int adt7470_probe(struct i2c_client *client, |
@@ -221,19 +230,13 @@ static void adt7470_init_client(struct i2c_client *client) | |||
221 | } | 230 | } |
222 | } | 231 | } |
223 | 232 | ||
224 | static struct adt7470_data *adt7470_update_device(struct device *dev) | 233 | /* Probe for temperature sensors. Assumes lock is held */ |
234 | static int adt7470_read_temperatures(struct i2c_client *client, | ||
235 | struct adt7470_data *data) | ||
225 | { | 236 | { |
226 | struct i2c_client *client = to_i2c_client(dev); | 237 | unsigned long res; |
227 | struct adt7470_data *data = i2c_get_clientdata(client); | ||
228 | unsigned long local_jiffies = jiffies; | ||
229 | u8 cfg, pwm[4], pwm_cfg[2]; | ||
230 | int i; | 238 | int i; |
231 | 239 | u8 cfg, pwm[4], pwm_cfg[2]; | |
232 | mutex_lock(&data->lock); | ||
233 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
234 | SENSOR_REFRESH_INTERVAL) | ||
235 | && data->sensors_valid) | ||
236 | goto no_sensor_update; | ||
237 | 240 | ||
238 | /* save pwm[1-4] config register */ | 241 | /* save pwm[1-4] config register */ |
239 | pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0)); | 242 | pwm_cfg[0] = i2c_smbus_read_byte_data(client, ADT7470_REG_PWM_CFG(0)); |
@@ -259,9 +262,9 @@ static struct adt7470_data *adt7470_update_device(struct device *dev) | |||
259 | i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); | 262 | i2c_smbus_write_byte_data(client, ADT7470_REG_CFG, cfg); |
260 | 263 | ||
261 | /* Delay is 200ms * number of temp sensors. */ | 264 | /* Delay is 200ms * number of temp sensors. */ |
262 | msleep((data->num_temp_sensors >= 0 ? | 265 | res = msleep_interruptible((data->num_temp_sensors >= 0 ? |
263 | data->num_temp_sensors * 200 : | 266 | data->num_temp_sensors * 200 : |
264 | TEMP_COLLECTION_TIME)); | 267 | TEMP_COLLECTION_TIME)); |
265 | 268 | ||
266 | /* done reading temperature sensors */ | 269 | /* done reading temperature sensors */ |
267 | cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); | 270 | cfg = i2c_smbus_read_byte_data(client, ADT7470_REG_CFG); |
@@ -272,15 +275,81 @@ static struct adt7470_data *adt7470_update_device(struct device *dev) | |||
272 | i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]); | 275 | i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(0), pwm_cfg[0]); |
273 | i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]); | 276 | i2c_smbus_write_byte_data(client, ADT7470_REG_PWM_CFG(2), pwm_cfg[1]); |
274 | 277 | ||
275 | for (i = 0; i < ADT7470_TEMP_COUNT; i++) | 278 | if (res) { |
279 | printk(KERN_ERR "ha ha, interrupted"); | ||
280 | return -EAGAIN; | ||
281 | } | ||
282 | |||
283 | /* Only count fans if we have to */ | ||
284 | if (data->num_temp_sensors >= 0) | ||
285 | return 0; | ||
286 | |||
287 | for (i = 0; i < ADT7470_TEMP_COUNT; i++) { | ||
276 | data->temp[i] = i2c_smbus_read_byte_data(client, | 288 | data->temp[i] = i2c_smbus_read_byte_data(client, |
277 | ADT7470_TEMP_REG(i)); | 289 | ADT7470_TEMP_REG(i)); |
290 | if (data->temp[i]) | ||
291 | data->num_temp_sensors = i + 1; | ||
292 | } | ||
293 | data->temperatures_probed = 1; | ||
294 | return 0; | ||
295 | } | ||
278 | 296 | ||
279 | /* Figure out the number of temp sensors */ | 297 | static int adt7470_update_thread(void *p) |
280 | if (data->num_temp_sensors < 0) | 298 | { |
299 | struct i2c_client *client = p; | ||
300 | struct adt7470_data *data = i2c_get_clientdata(client); | ||
301 | |||
302 | while (!kthread_should_stop()) { | ||
303 | mutex_lock(&data->lock); | ||
304 | adt7470_read_temperatures(client, data); | ||
305 | mutex_unlock(&data->lock); | ||
306 | if (kthread_should_stop()) | ||
307 | break; | ||
308 | msleep_interruptible(data->auto_update_interval); | ||
309 | } | ||
310 | |||
311 | complete_all(&data->auto_update_stop); | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | static struct adt7470_data *adt7470_update_device(struct device *dev) | ||
316 | { | ||
317 | struct i2c_client *client = to_i2c_client(dev); | ||
318 | struct adt7470_data *data = i2c_get_clientdata(client); | ||
319 | unsigned long local_jiffies = jiffies; | ||
320 | u8 cfg; | ||
321 | int i; | ||
322 | int need_sensors = 1; | ||
323 | int need_limits = 1; | ||
324 | |||
325 | /* | ||
326 | * Figure out if we need to update the shadow registers. | ||
327 | * Lockless means that we may occasionally report out of | ||
328 | * date data. | ||
329 | */ | ||
330 | if (time_before(local_jiffies, data->sensors_last_updated + | ||
331 | SENSOR_REFRESH_INTERVAL) && | ||
332 | data->sensors_valid) | ||
333 | need_sensors = 0; | ||
334 | |||
335 | if (time_before(local_jiffies, data->limits_last_updated + | ||
336 | LIMIT_REFRESH_INTERVAL) && | ||
337 | data->limits_valid) | ||
338 | need_limits = 0; | ||
339 | |||
340 | if (!need_sensors && !need_limits) | ||
341 | return data; | ||
342 | |||
343 | mutex_lock(&data->lock); | ||
344 | if (!need_sensors) | ||
345 | goto no_sensor_update; | ||
346 | |||
347 | if (!data->temperatures_probed) | ||
348 | adt7470_read_temperatures(client, data); | ||
349 | else | ||
281 | for (i = 0; i < ADT7470_TEMP_COUNT; i++) | 350 | for (i = 0; i < ADT7470_TEMP_COUNT; i++) |
282 | if (data->temp[i]) | 351 | data->temp[i] = i2c_smbus_read_byte_data(client, |
283 | data->num_temp_sensors = i + 1; | 352 | ADT7470_TEMP_REG(i)); |
284 | 353 | ||
285 | for (i = 0; i < ADT7470_FAN_COUNT; i++) | 354 | for (i = 0; i < ADT7470_FAN_COUNT; i++) |
286 | data->fan[i] = adt7470_read_word_data(client, | 355 | data->fan[i] = adt7470_read_word_data(client, |
@@ -329,9 +398,7 @@ static struct adt7470_data *adt7470_update_device(struct device *dev) | |||
329 | data->sensors_valid = 1; | 398 | data->sensors_valid = 1; |
330 | 399 | ||
331 | no_sensor_update: | 400 | no_sensor_update: |
332 | if (time_before(local_jiffies, data->limits_last_updated + | 401 | if (!need_limits) |
333 | LIMIT_REFRESH_INTERVAL) | ||
334 | && data->limits_valid) | ||
335 | goto out; | 402 | goto out; |
336 | 403 | ||
337 | for (i = 0; i < ADT7470_TEMP_COUNT; i++) { | 404 | for (i = 0; i < ADT7470_TEMP_COUNT; i++) { |
@@ -365,6 +432,35 @@ out: | |||
365 | return data; | 432 | return data; |
366 | } | 433 | } |
367 | 434 | ||
435 | static ssize_t show_auto_update_interval(struct device *dev, | ||
436 | struct device_attribute *devattr, | ||
437 | char *buf) | ||
438 | { | ||
439 | struct adt7470_data *data = adt7470_update_device(dev); | ||
440 | return sprintf(buf, "%d\n", data->auto_update_interval); | ||
441 | } | ||
442 | |||
443 | static ssize_t set_auto_update_interval(struct device *dev, | ||
444 | struct device_attribute *devattr, | ||
445 | const char *buf, | ||
446 | size_t count) | ||
447 | { | ||
448 | struct i2c_client *client = to_i2c_client(dev); | ||
449 | struct adt7470_data *data = i2c_get_clientdata(client); | ||
450 | long temp; | ||
451 | |||
452 | if (strict_strtol(buf, 10, &temp)) | ||
453 | return -EINVAL; | ||
454 | |||
455 | temp = SENSORS_LIMIT(temp, 0, 60000); | ||
456 | |||
457 | mutex_lock(&data->lock); | ||
458 | data->auto_update_interval = temp; | ||
459 | mutex_unlock(&data->lock); | ||
460 | |||
461 | return count; | ||
462 | } | ||
463 | |||
368 | static ssize_t show_num_temp_sensors(struct device *dev, | 464 | static ssize_t show_num_temp_sensors(struct device *dev, |
369 | struct device_attribute *devattr, | 465 | struct device_attribute *devattr, |
370 | char *buf) | 466 | char *buf) |
@@ -389,6 +485,8 @@ static ssize_t set_num_temp_sensors(struct device *dev, | |||
389 | 485 | ||
390 | mutex_lock(&data->lock); | 486 | mutex_lock(&data->lock); |
391 | data->num_temp_sensors = temp; | 487 | data->num_temp_sensors = temp; |
488 | if (temp < 0) | ||
489 | data->temperatures_probed = 0; | ||
392 | mutex_unlock(&data->lock); | 490 | mutex_unlock(&data->lock); |
393 | 491 | ||
394 | return count; | 492 | return count; |
@@ -862,6 +960,8 @@ static ssize_t show_alarm(struct device *dev, | |||
862 | static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL); | 960 | static DEVICE_ATTR(alarm_mask, S_IRUGO, show_alarm_mask, NULL); |
863 | static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, | 961 | static DEVICE_ATTR(num_temp_sensors, S_IWUSR | S_IRUGO, show_num_temp_sensors, |
864 | set_num_temp_sensors); | 962 | set_num_temp_sensors); |
963 | static DEVICE_ATTR(auto_update_interval, S_IWUSR | S_IRUGO, | ||
964 | show_auto_update_interval, set_auto_update_interval); | ||
865 | 965 | ||
866 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, | 966 | static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, |
867 | set_temp_max, 0); | 967 | set_temp_max, 0); |
@@ -1035,6 +1135,7 @@ static struct attribute *adt7470_attr[] = | |||
1035 | { | 1135 | { |
1036 | &dev_attr_alarm_mask.attr, | 1136 | &dev_attr_alarm_mask.attr, |
1037 | &dev_attr_num_temp_sensors.attr, | 1137 | &dev_attr_num_temp_sensors.attr, |
1138 | &dev_attr_auto_update_interval.attr, | ||
1038 | &sensor_dev_attr_temp1_max.dev_attr.attr, | 1139 | &sensor_dev_attr_temp1_max.dev_attr.attr, |
1039 | &sensor_dev_attr_temp2_max.dev_attr.attr, | 1140 | &sensor_dev_attr_temp2_max.dev_attr.attr, |
1040 | &sensor_dev_attr_temp3_max.dev_attr.attr, | 1141 | &sensor_dev_attr_temp3_max.dev_attr.attr, |
@@ -1168,6 +1269,7 @@ static int adt7470_probe(struct i2c_client *client, | |||
1168 | } | 1269 | } |
1169 | 1270 | ||
1170 | data->num_temp_sensors = -1; | 1271 | data->num_temp_sensors = -1; |
1272 | data->auto_update_interval = AUTO_UPDATE_INTERVAL; | ||
1171 | 1273 | ||
1172 | i2c_set_clientdata(client, data); | 1274 | i2c_set_clientdata(client, data); |
1173 | mutex_init(&data->lock); | 1275 | mutex_init(&data->lock); |
@@ -1188,8 +1290,16 @@ static int adt7470_probe(struct i2c_client *client, | |||
1188 | goto exit_remove; | 1290 | goto exit_remove; |
1189 | } | 1291 | } |
1190 | 1292 | ||
1293 | init_completion(&data->auto_update_stop); | ||
1294 | data->auto_update = kthread_run(adt7470_update_thread, client, | ||
1295 | dev_name(data->hwmon_dev)); | ||
1296 | if (IS_ERR(data->auto_update)) | ||
1297 | goto exit_unregister; | ||
1298 | |||
1191 | return 0; | 1299 | return 0; |
1192 | 1300 | ||
1301 | exit_unregister: | ||
1302 | hwmon_device_unregister(data->hwmon_dev); | ||
1193 | exit_remove: | 1303 | exit_remove: |
1194 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | 1304 | sysfs_remove_group(&client->dev.kobj, &data->attrs); |
1195 | exit_free: | 1305 | exit_free: |
@@ -1202,6 +1312,8 @@ static int adt7470_remove(struct i2c_client *client) | |||
1202 | { | 1312 | { |
1203 | struct adt7470_data *data = i2c_get_clientdata(client); | 1313 | struct adt7470_data *data = i2c_get_clientdata(client); |
1204 | 1314 | ||
1315 | kthread_stop(data->auto_update); | ||
1316 | wait_for_completion(&data->auto_update_stop); | ||
1205 | hwmon_device_unregister(data->hwmon_dev); | 1317 | hwmon_device_unregister(data->hwmon_dev); |
1206 | sysfs_remove_group(&client->dev.kobj, &data->attrs); | 1318 | sysfs_remove_group(&client->dev.kobj, &data->attrs); |
1207 | kfree(data); | 1319 | kfree(data); |