diff options
author | Guenter Roeck <linux@roeck-us.net> | 2012-12-04 06:13:34 -0500 |
---|---|---|
committer | Guenter Roeck <linux@roeck-us.net> | 2013-04-08 00:16:38 -0400 |
commit | a6bd587842772cd3e63a689c7ff4d64cf25284a3 (patch) | |
tree | 484cc1e651d30adfd71debbce075eb303fd2c127 | |
parent | 9de2e2e84e7d52e4c2a9e1a1e21ab6ac686233c0 (diff) |
hwmon: (nct6775) Add case open detection
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
-rw-r--r-- | drivers/hwmon/nct6775.c | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/drivers/hwmon/nct6775.c b/drivers/hwmon/nct6775.c index f75cd8231534..435691febe9b 100644 --- a/drivers/hwmon/nct6775.c +++ b/drivers/hwmon/nct6775.c | |||
@@ -76,6 +76,7 @@ MODULE_PARM_DESC(force_id, "Override the detected device ID"); | |||
76 | * Super-I/O constants and functions | 76 | * Super-I/O constants and functions |
77 | */ | 77 | */ |
78 | 78 | ||
79 | #define NCT6775_LD_ACPI 0x0a | ||
79 | #define NCT6775_LD_HWM 0x0b | 80 | #define NCT6775_LD_HWM 0x0b |
80 | #define NCT6775_LD_VID 0x0d | 81 | #define NCT6775_LD_VID 0x0d |
81 | 82 | ||
@@ -186,6 +187,11 @@ static const s8 NCT6775_ALARM_BITS[] = { | |||
186 | 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ | 187 | 4, 5, 13, -1, -1, -1, /* temp1..temp6 */ |
187 | 12, -1 }; /* intrusion0, intrusion1 */ | 188 | 12, -1 }; /* intrusion0, intrusion1 */ |
188 | 189 | ||
190 | #define INTRUSION_ALARM_BASE 30 | ||
191 | |||
192 | static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee }; | ||
193 | static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 }; | ||
194 | |||
189 | /* NCT6776 specific data */ | 195 | /* NCT6776 specific data */ |
190 | 196 | ||
191 | static const s8 NCT6776_ALARM_BITS[] = { | 197 | static const s8 NCT6776_ALARM_BITS[] = { |
@@ -694,6 +700,56 @@ show_vid(struct device *dev, struct device_attribute *attr, char *buf) | |||
694 | 700 | ||
695 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 701 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
696 | 702 | ||
703 | /* Case open detection */ | ||
704 | |||
705 | static ssize_t | ||
706 | clear_caseopen(struct device *dev, struct device_attribute *attr, | ||
707 | const char *buf, size_t count) | ||
708 | { | ||
709 | struct nct6775_data *data = dev_get_drvdata(dev); | ||
710 | struct nct6775_sio_data *sio_data = dev->platform_data; | ||
711 | int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE; | ||
712 | unsigned long val; | ||
713 | u8 reg; | ||
714 | int ret; | ||
715 | |||
716 | if (kstrtoul(buf, 10, &val) || val != 0) | ||
717 | return -EINVAL; | ||
718 | |||
719 | mutex_lock(&data->update_lock); | ||
720 | |||
721 | /* | ||
722 | * Use CR registers to clear caseopen status. | ||
723 | * The CR registers are the same for all chips, and not all chips | ||
724 | * support clearing the caseopen status through "regular" registers. | ||
725 | */ | ||
726 | ret = superio_enter(sio_data->sioreg); | ||
727 | if (ret) { | ||
728 | count = ret; | ||
729 | goto error; | ||
730 | } | ||
731 | |||
732 | superio_select(sio_data->sioreg, NCT6775_LD_ACPI); | ||
733 | reg = superio_inb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr]); | ||
734 | reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr]; | ||
735 | superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); | ||
736 | reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr]; | ||
737 | superio_outb(sio_data->sioreg, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg); | ||
738 | superio_exit(sio_data->sioreg); | ||
739 | |||
740 | data->valid = false; /* Force cache refresh */ | ||
741 | error: | ||
742 | mutex_unlock(&data->update_lock); | ||
743 | return count; | ||
744 | } | ||
745 | |||
746 | static struct sensor_device_attribute sda_caseopen[] = { | ||
747 | SENSOR_ATTR(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm, | ||
748 | clear_caseopen, INTRUSION_ALARM_BASE), | ||
749 | SENSOR_ATTR(intrusion1_alarm, S_IWUSR | S_IRUGO, show_alarm, | ||
750 | clear_caseopen, INTRUSION_ALARM_BASE + 1), | ||
751 | }; | ||
752 | |||
697 | /* | 753 | /* |
698 | * Driver and device management | 754 | * Driver and device management |
699 | */ | 755 | */ |
@@ -710,6 +766,9 @@ static void nct6775_device_remove_files(struct device *dev) | |||
710 | for (i = 0; i < data->in_num; i++) | 766 | for (i = 0; i < data->in_num; i++) |
711 | sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); | 767 | sysfs_remove_group(&dev->kobj, &nct6775_group_in[i]); |
712 | 768 | ||
769 | device_remove_file(dev, &sda_caseopen[0].dev_attr); | ||
770 | device_remove_file(dev, &sda_caseopen[1].dev_attr); | ||
771 | |||
713 | device_remove_file(dev, &dev_attr_name); | 772 | device_remove_file(dev, &dev_attr_name); |
714 | device_remove_file(dev, &dev_attr_cpu0_vid); | 773 | device_remove_file(dev, &dev_attr_cpu0_vid); |
715 | } | 774 | } |
@@ -828,6 +887,14 @@ static int nct6775_probe(struct platform_device *pdev) | |||
828 | goto exit_remove; | 887 | goto exit_remove; |
829 | } | 888 | } |
830 | 889 | ||
890 | for (i = 0; i < ARRAY_SIZE(sda_caseopen); i++) { | ||
891 | if (data->ALARM_BITS[INTRUSION_ALARM_BASE + i] < 0) | ||
892 | continue; | ||
893 | err = device_create_file(dev, &sda_caseopen[i].dev_attr); | ||
894 | if (err) | ||
895 | goto exit_remove; | ||
896 | } | ||
897 | |||
831 | err = device_create_file(dev, &dev_attr_name); | 898 | err = device_create_file(dev, &dev_attr_name); |
832 | if (err) | 899 | if (err) |
833 | goto exit_remove; | 900 | goto exit_remove; |