diff options
author | Dmitry Artamonow <mad_soft@inbox.ru> | 2011-08-12 16:41:11 -0400 |
---|---|---|
committer | Guenter Roeck <guenter.roeck@ericsson.com> | 2011-10-24 14:09:32 -0400 |
commit | 363a12a49968103ea2c5493932d417d73bc099b7 (patch) | |
tree | 66dac36f101c2b7a9f03217d9d508c3231138257 /drivers | |
parent | c3b92c8787367a8bb53d57d9789b558f1295cc96 (diff) |
hwmon: (w83627ehf) add caseopen detection
Export caseopen alarm status into userspace for Winbond W83627*
and Nuvoton NCT677[56] chips and implement alarm clear attribute.
Second caseopen alarm on NCT6776 is also supported.
Signed-off-by: Dmitry Artamonow <mad_soft@inbox.ru>
Signed-off-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/hwmon/w83627ehf.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c index 36d7f270b14d..e1736b80b6b0 100644 --- a/drivers/hwmon/w83627ehf.c +++ b/drivers/hwmon/w83627ehf.c | |||
@@ -197,6 +197,9 @@ static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 }; | |||
197 | #define W83627EHF_REG_ALARM2 0x45A | 197 | #define W83627EHF_REG_ALARM2 0x45A |
198 | #define W83627EHF_REG_ALARM3 0x45B | 198 | #define W83627EHF_REG_ALARM3 0x45B |
199 | 199 | ||
200 | #define W83627EHF_REG_CASEOPEN_DET 0x42 /* SMI STATUS #2 */ | ||
201 | #define W83627EHF_REG_CASEOPEN_CLR 0x46 /* SMI MASK #3 */ | ||
202 | |||
200 | /* SmartFan registers */ | 203 | /* SmartFan registers */ |
201 | #define W83627EHF_REG_FAN_STEPUP_TIME 0x0f | 204 | #define W83627EHF_REG_FAN_STEPUP_TIME 0x0f |
202 | #define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e | 205 | #define W83627EHF_REG_FAN_STEPDOWN_TIME 0x0e |
@@ -469,6 +472,7 @@ struct w83627ehf_data { | |||
469 | s16 temp_max[9]; | 472 | s16 temp_max[9]; |
470 | s16 temp_max_hyst[9]; | 473 | s16 temp_max_hyst[9]; |
471 | u32 alarms; | 474 | u32 alarms; |
475 | u8 caseopen; | ||
472 | 476 | ||
473 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ | 477 | u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */ |
474 | u8 pwm_enable[4]; /* 1->manual | 478 | u8 pwm_enable[4]; /* 1->manual |
@@ -874,6 +878,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev) | |||
874 | (w83627ehf_read_value(data, | 878 | (w83627ehf_read_value(data, |
875 | W83627EHF_REG_ALARM3) << 16); | 879 | W83627EHF_REG_ALARM3) << 16); |
876 | 880 | ||
881 | data->caseopen = w83627ehf_read_value(data, | ||
882 | W83627EHF_REG_CASEOPEN_DET); | ||
883 | |||
877 | data->last_updated = jiffies; | 884 | data->last_updated = jiffies; |
878 | data->valid = 1; | 885 | data->valid = 1; |
879 | } | 886 | } |
@@ -1655,6 +1662,48 @@ show_vid(struct device *dev, struct device_attribute *attr, char *buf) | |||
1655 | } | 1662 | } |
1656 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); | 1663 | static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL); |
1657 | 1664 | ||
1665 | |||
1666 | /* Case open detection */ | ||
1667 | |||
1668 | static ssize_t | ||
1669 | show_caseopen(struct device *dev, struct device_attribute *attr, char *buf) | ||
1670 | { | ||
1671 | struct w83627ehf_data *data = w83627ehf_update_device(dev); | ||
1672 | |||
1673 | return sprintf(buf, "%d\n", | ||
1674 | !!(data->caseopen & to_sensor_dev_attr_2(attr)->index)); | ||
1675 | } | ||
1676 | |||
1677 | static ssize_t | ||
1678 | clear_caseopen(struct device *dev, struct device_attribute *attr, | ||
1679 | const char *buf, size_t count) | ||
1680 | { | ||
1681 | struct w83627ehf_data *data = dev_get_drvdata(dev); | ||
1682 | unsigned long val; | ||
1683 | u16 reg, mask; | ||
1684 | |||
1685 | if (strict_strtoul(buf, 10, &val) || val != 0) | ||
1686 | return -EINVAL; | ||
1687 | |||
1688 | mask = to_sensor_dev_attr_2(attr)->nr; | ||
1689 | |||
1690 | mutex_lock(&data->update_lock); | ||
1691 | reg = w83627ehf_read_value(data, W83627EHF_REG_CASEOPEN_CLR); | ||
1692 | w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg | mask); | ||
1693 | w83627ehf_write_value(data, W83627EHF_REG_CASEOPEN_CLR, reg & ~mask); | ||
1694 | data->valid = 0; /* Force cache refresh */ | ||
1695 | mutex_unlock(&data->update_lock); | ||
1696 | |||
1697 | return count; | ||
1698 | } | ||
1699 | |||
1700 | static struct sensor_device_attribute_2 sda_caseopen[] = { | ||
1701 | SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_caseopen, | ||
1702 | clear_caseopen, 0x80, 0x10), | ||
1703 | SENSOR_ATTR_2(intrusion1_alarm, S_IWUSR | S_IRUGO, show_caseopen, | ||
1704 | clear_caseopen, 0x40, 0x40), | ||
1705 | }; | ||
1706 | |||
1658 | /* | 1707 | /* |
1659 | * Driver and device management | 1708 | * Driver and device management |
1660 | */ | 1709 | */ |
@@ -1711,6 +1760,9 @@ static void w83627ehf_device_remove_files(struct device *dev) | |||
1711 | device_remove_file(dev, &sda_temp_type[i].dev_attr); | 1760 | device_remove_file(dev, &sda_temp_type[i].dev_attr); |
1712 | } | 1761 | } |
1713 | 1762 | ||
1763 | device_remove_file(dev, &sda_caseopen[0].dev_attr); | ||
1764 | device_remove_file(dev, &sda_caseopen[1].dev_attr); | ||
1765 | |||
1714 | device_remove_file(dev, &dev_attr_name); | 1766 | device_remove_file(dev, &dev_attr_name); |
1715 | device_remove_file(dev, &dev_attr_cpu0_vid); | 1767 | device_remove_file(dev, &dev_attr_cpu0_vid); |
1716 | } | 1768 | } |
@@ -2269,6 +2321,16 @@ static int __devinit w83627ehf_probe(struct platform_device *pdev) | |||
2269 | goto exit_remove; | 2321 | goto exit_remove; |
2270 | } | 2322 | } |
2271 | 2323 | ||
2324 | err = device_create_file(dev, &sda_caseopen[0].dev_attr); | ||
2325 | if (err) | ||
2326 | goto exit_remove; | ||
2327 | |||
2328 | if (sio_data->kind == nct6776) { | ||
2329 | err = device_create_file(dev, &sda_caseopen[1].dev_attr); | ||
2330 | if (err) | ||
2331 | goto exit_remove; | ||
2332 | } | ||
2333 | |||
2272 | err = device_create_file(dev, &dev_attr_name); | 2334 | err = device_create_file(dev, &dev_attr_name); |
2273 | if (err) | 2335 | if (err) |
2274 | goto exit_remove; | 2336 | goto exit_remove; |