summaryrefslogtreecommitdiff
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorJean Delvare <khali@linux-fr.org>2010-11-15 23:38:56 +0300
committerJean Delvare <khali@endymion.delvare>2010-11-15 23:38:56 +0300
commitcf6b9ea661ef4f20b4a4cba1a232a732339aae2c (patch)
treed12db9d301146d533120686d7da1bf84a3068c0a /drivers/hwmon
parent2a2d27da00250c9f117e35653ed5a6a3212e5d77 (diff)
downloadlinux-cf6b9ea661ef4f20b4a4cba1a232a732339aae2c.tar.xz
hwmon: (w83795) Read the intrusion state properly
We can't read the intrusion state from the real-time alarm registers as we do for all other alarm flags, because real-time alarm bits don't stick (by definition) and the intrusion state has to stick until explicitly cleared (otherwise it has little value.) So we have to use the interrupt status register instead, which is read from the same address but with a configuration bit flipped in another register. Signed-off-by: Jean Delvare <khali@linux-fr.org> Acked-by: Guenter Roeck <guenter.roeck@ericsson.com>
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/w83795.c23
1 files changed, 20 insertions, 3 deletions
diff --git a/drivers/hwmon/w83795.c b/drivers/hwmon/w83795.c
index 400558d97f3d..600b2adbbd49 100644
--- a/drivers/hwmon/w83795.c
+++ b/drivers/hwmon/w83795.c
@@ -165,10 +165,11 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
#define W83795_REG_VID_CTRL 0x6A
+#define W83795_REG_ALARM_CTRL 0x40
+#define ALARM_CTRL_RTSACS (1 << 7)
#define W83795_REG_ALARM(index) (0x41 + (index))
-#define W83795_REG_BEEP(index) (0x50 + (index))
-
#define W83795_REG_CLR_CHASSIS 0x4D
+#define W83795_REG_BEEP(index) (0x50 + (index))
#define W83795_REG_FCMS1 0x201
@@ -585,6 +586,7 @@ static struct w83795_data *w83795_update_device(struct device *dev)
struct i2c_client *client = to_i2c_client(dev);
struct w83795_data *data = i2c_get_clientdata(client);
u16 tmp;
+ u8 intrusion;
int i;
mutex_lock(&data->update_lock);
@@ -656,9 +658,24 @@ static struct w83795_data *w83795_update_device(struct device *dev)
w83795_read(client, W83795_REG_PWM(i, PWM_OUTPUT));
}
- /* update alarm */
+ /* Update intrusion and alarms
+ * It is important to read intrusion first, because reading from
+ * register SMI STS6 clears the interrupt status temporarily. */
+ tmp = w83795_read(client, W83795_REG_ALARM_CTRL);
+ /* Switch to interrupt status for intrusion if needed */
+ if (tmp & ALARM_CTRL_RTSACS)
+ w83795_write(client, W83795_REG_ALARM_CTRL,
+ tmp & ~ALARM_CTRL_RTSACS);
+ intrusion = w83795_read(client, W83795_REG_ALARM(5)) & (1 << 6);
+ /* Switch to real-time alarms */
+ w83795_write(client, W83795_REG_ALARM_CTRL, tmp | ALARM_CTRL_RTSACS);
for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
+ data->alarms[5] |= intrusion;
+ /* Restore original configuration if needed */
+ if (!(tmp & ALARM_CTRL_RTSACS))
+ w83795_write(client, W83795_REG_ALARM_CTRL,
+ tmp & ~ALARM_CTRL_RTSACS);
data->last_updated = jiffies;
data->valid = 1;