diff options
Diffstat (limited to 'drivers/hwmon/lm63.c')
-rw-r--r-- | drivers/hwmon/lm63.c | 96 |
1 files changed, 71 insertions, 25 deletions
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c index 071f0fc6adec..d69f3cf07122 100644 --- a/drivers/hwmon/lm63.c +++ b/drivers/hwmon/lm63.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor | 2 | * lm63.c - driver for the National Semiconductor LM63 temperature sensor |
3 | * with integrated fan control | 3 | * with integrated fan control |
4 | * Copyright (C) 2004-2005 Jean Delvare <khali@linux-fr.org> | 4 | * Copyright (C) 2004-2006 Jean Delvare <khali@linux-fr.org> |
5 | * Based on the lm90 driver. | 5 | * Based on the lm90 driver. |
6 | * | 6 | * |
7 | * The LM63 is a sensor chip made by National Semiconductor. It measures | 7 | * The LM63 is a sensor chip made by National Semiconductor. It measures |
@@ -46,6 +46,7 @@ | |||
46 | #include <linux/hwmon.h> | 46 | #include <linux/hwmon.h> |
47 | #include <linux/err.h> | 47 | #include <linux/err.h> |
48 | #include <linux/mutex.h> | 48 | #include <linux/mutex.h> |
49 | #include <linux/sysfs.h> | ||
49 | 50 | ||
50 | /* | 51 | /* |
51 | * Addresses to scan | 52 | * Addresses to scan |
@@ -330,6 +331,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *dummy, | |||
330 | return sprintf(buf, "%u\n", data->alarms); | 331 | return sprintf(buf, "%u\n", data->alarms); |
331 | } | 332 | } |
332 | 333 | ||
334 | static ssize_t show_alarm(struct device *dev, struct device_attribute *devattr, | ||
335 | char *buf) | ||
336 | { | ||
337 | struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); | ||
338 | struct lm63_data *data = lm63_update_device(dev); | ||
339 | int bitnr = attr->index; | ||
340 | |||
341 | return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1); | ||
342 | } | ||
343 | |||
333 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); | 344 | static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0); |
334 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, | 345 | static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan, |
335 | set_fan, 1); | 346 | set_fan, 1); |
@@ -350,8 +361,52 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp8, NULL, 2); | |||
350 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, | 361 | static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst, |
351 | set_temp2_crit_hyst); | 362 | set_temp2_crit_hyst); |
352 | 363 | ||
364 | /* Individual alarm files */ | ||
365 | static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0); | ||
366 | static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1); | ||
367 | static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2); | ||
368 | static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3); | ||
369 | static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4); | ||
370 | static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6); | ||
371 | /* Raw alarm file for compatibility */ | ||
353 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); | 372 | static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL); |
354 | 373 | ||
374 | static struct attribute *lm63_attributes[] = { | ||
375 | &dev_attr_pwm1.attr, | ||
376 | &dev_attr_pwm1_enable.attr, | ||
377 | &sensor_dev_attr_temp1_input.dev_attr.attr, | ||
378 | &sensor_dev_attr_temp2_input.dev_attr.attr, | ||
379 | &sensor_dev_attr_temp2_min.dev_attr.attr, | ||
380 | &sensor_dev_attr_temp1_max.dev_attr.attr, | ||
381 | &sensor_dev_attr_temp2_max.dev_attr.attr, | ||
382 | &sensor_dev_attr_temp2_crit.dev_attr.attr, | ||
383 | &dev_attr_temp2_crit_hyst.attr, | ||
384 | |||
385 | &sensor_dev_attr_temp2_crit_alarm.dev_attr.attr, | ||
386 | &sensor_dev_attr_temp2_input_fault.dev_attr.attr, | ||
387 | &sensor_dev_attr_temp2_min_alarm.dev_attr.attr, | ||
388 | &sensor_dev_attr_temp2_max_alarm.dev_attr.attr, | ||
389 | &sensor_dev_attr_temp1_max_alarm.dev_attr.attr, | ||
390 | &dev_attr_alarms.attr, | ||
391 | NULL | ||
392 | }; | ||
393 | |||
394 | static const struct attribute_group lm63_group = { | ||
395 | .attrs = lm63_attributes, | ||
396 | }; | ||
397 | |||
398 | static struct attribute *lm63_attributes_fan1[] = { | ||
399 | &sensor_dev_attr_fan1_input.dev_attr.attr, | ||
400 | &sensor_dev_attr_fan1_min.dev_attr.attr, | ||
401 | |||
402 | &sensor_dev_attr_fan1_min_alarm.dev_attr.attr, | ||
403 | NULL | ||
404 | }; | ||
405 | |||
406 | static const struct attribute_group lm63_group_fan1 = { | ||
407 | .attrs = lm63_attributes_fan1, | ||
408 | }; | ||
409 | |||
355 | /* | 410 | /* |
356 | * Real code | 411 | * Real code |
357 | */ | 412 | */ |
@@ -438,37 +493,26 @@ static int lm63_detect(struct i2c_adapter *adapter, int address, int kind) | |||
438 | lm63_init_client(new_client); | 493 | lm63_init_client(new_client); |
439 | 494 | ||
440 | /* Register sysfs hooks */ | 495 | /* Register sysfs hooks */ |
441 | data->class_dev = hwmon_device_register(&new_client->dev); | 496 | if ((err = sysfs_create_group(&new_client->dev.kobj, |
442 | if (IS_ERR(data->class_dev)) { | 497 | &lm63_group))) |
443 | err = PTR_ERR(data->class_dev); | ||
444 | goto exit_detach; | 498 | goto exit_detach; |
499 | if (data->config & 0x04) { /* tachometer enabled */ | ||
500 | if ((err = sysfs_create_group(&new_client->dev.kobj, | ||
501 | &lm63_group_fan1))) | ||
502 | goto exit_remove_files; | ||
445 | } | 503 | } |
446 | 504 | ||
447 | if (data->config & 0x04) { /* tachometer enabled */ | 505 | data->class_dev = hwmon_device_register(&new_client->dev); |
448 | device_create_file(&new_client->dev, | 506 | if (IS_ERR(data->class_dev)) { |
449 | &sensor_dev_attr_fan1_input.dev_attr); | 507 | err = PTR_ERR(data->class_dev); |
450 | device_create_file(&new_client->dev, | 508 | goto exit_remove_files; |
451 | &sensor_dev_attr_fan1_min.dev_attr); | ||
452 | } | 509 | } |
453 | device_create_file(&new_client->dev, &dev_attr_pwm1); | ||
454 | device_create_file(&new_client->dev, &dev_attr_pwm1_enable); | ||
455 | device_create_file(&new_client->dev, | ||
456 | &sensor_dev_attr_temp1_input.dev_attr); | ||
457 | device_create_file(&new_client->dev, | ||
458 | &sensor_dev_attr_temp2_input.dev_attr); | ||
459 | device_create_file(&new_client->dev, | ||
460 | &sensor_dev_attr_temp2_min.dev_attr); | ||
461 | device_create_file(&new_client->dev, | ||
462 | &sensor_dev_attr_temp1_max.dev_attr); | ||
463 | device_create_file(&new_client->dev, | ||
464 | &sensor_dev_attr_temp2_max.dev_attr); | ||
465 | device_create_file(&new_client->dev, | ||
466 | &sensor_dev_attr_temp2_crit.dev_attr); | ||
467 | device_create_file(&new_client->dev, &dev_attr_temp2_crit_hyst); | ||
468 | device_create_file(&new_client->dev, &dev_attr_alarms); | ||
469 | 510 | ||
470 | return 0; | 511 | return 0; |
471 | 512 | ||
513 | exit_remove_files: | ||
514 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group); | ||
515 | sysfs_remove_group(&new_client->dev.kobj, &lm63_group_fan1); | ||
472 | exit_detach: | 516 | exit_detach: |
473 | i2c_detach_client(new_client); | 517 | i2c_detach_client(new_client); |
474 | exit_free: | 518 | exit_free: |
@@ -518,6 +562,8 @@ static int lm63_detach_client(struct i2c_client *client) | |||
518 | int err; | 562 | int err; |
519 | 563 | ||
520 | hwmon_device_unregister(data->class_dev); | 564 | hwmon_device_unregister(data->class_dev); |
565 | sysfs_remove_group(&client->dev.kobj, &lm63_group); | ||
566 | sysfs_remove_group(&client->dev.kobj, &lm63_group_fan1); | ||
521 | 567 | ||
522 | if ((err = i2c_detach_client(client))) | 568 | if ((err = i2c_detach_client(client))) |
523 | return err; | 569 | return err; |