Merge branch 'for-linus' of git://www.jni.nu/cris
[pandora-kernel.git] / drivers / hwmon / w83795.c
index aea3275..1d840aa 100644 (file)
@@ -2,6 +2,7 @@
  *  w83795.c - Linux kernel driver for hardware monitoring
  *  Copyright (C) 2008 Nuvoton Technology Corp.
  *                Wei Song
+ *  Copyright (C) 2010 Jean Delvare <khali@linux-fr.org>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -66,23 +67,6 @@ MODULE_PARM_DESC(reset, "Set to 1 to reset chip, not recommended");
 #define W83795_REG_FANIN_CTRL2         0x07
 #define W83795_REG_VMIGB_CTRL          0x08
 
-#define TEMP_CTRL_DISABLE              0
-#define TEMP_CTRL_TD                   1
-#define TEMP_CTRL_VSEN                 2
-#define TEMP_CTRL_TR                   3
-#define TEMP_CTRL_SHIFT                        4
-#define TEMP_CTRL_HASIN_SHIFT          5
-/* temp mode may effect VSEN17-12 (in20-15) */
-static const u16 W83795_REG_TEMP_CTRL[][6] = {
-       /* Disable, TD, VSEN, TR, register shift value, has_in shift num */
-       {0x00, 0x01, 0x02, 0x03, 0, 17},        /* TR1 */
-       {0x00, 0x04, 0x08, 0x0C, 2, 18},        /* TR2 */
-       {0x00, 0x10, 0x20, 0x30, 4, 19},        /* TR3 */
-       {0x00, 0x40, 0x80, 0xC0, 6, 20},        /* TR4 */
-       {0x00, 0x00, 0x02, 0x03, 0, 15},        /* TR5 */
-       {0x00, 0x00, 0x08, 0x0C, 2, 16},        /* TR6 */
-};
-
 #define TEMP_READ                      0
 #define TEMP_CRIT                      1
 #define TEMP_CRIT_HYST                 2
@@ -127,7 +111,6 @@ static const u16 W83795_REG_IN[][3] = {
        {0x24, 0xa2, 0xa3},     /* VSEN17 */
 };
 #define W83795_REG_VRLSB               0x3C
-#define VRLSB_SHIFT                    6
 
 static const u8 W83795_REG_IN_HL_LSB[] = {
        0x8e,   /* VSEN1-4 */
@@ -146,8 +129,6 @@ static const u8 W83795_REG_IN_HL_LSB[] = {
        (((type) == 1) ? W83795_REG_IN_HL_LSB[(index)] \
        : (W83795_REG_IN_HL_LSB[(index)] + 1))
 
-#define IN_LSB_REG_NUM                 10
-
 #define IN_LSB_SHIFT                   0
 #define IN_LSB_IDX                     1
 static const u8 IN_LSB_SHIFT_IDX[][2] = {
@@ -176,26 +157,20 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
 };
 
 
-/* 3VDD, 3VSB, VBAT * 0.006 */
-#define REST_VLT_BEGIN                 12  /* the 13th volt to 15th */
-#define REST_VLT_END                   14  /* the 13th volt to 15th */
-
 #define W83795_REG_FAN(index)          (0x2E + (index))
 #define W83795_REG_FAN_MIN_HL(index)   (0xB6 + (index))
 #define W83795_REG_FAN_MIN_LSB(index)  (0xC4 + (index) / 2)
 #define W83795_REG_FAN_MIN_LSB_SHIFT(index) \
-       (((index) % 1) ? 4 : 0)
+       (((index) & 1) ? 4 : 0)
 
 #define W83795_REG_VID_CTRL            0x6A
 
-#define ALARM_BEEP_REG_NUM             6
 #define W83795_REG_ALARM(index)                (0x41 + (index))
 #define W83795_REG_BEEP(index)         (0x50 + (index))
 
 #define W83795_REG_CLR_CHASSIS         0x4D
 
 
-#define W83795_REG_TEMP_NUM            6
 #define W83795_REG_FCMS1               0x201
 #define W83795_REG_FCMS2               0x208
 #define W83795_REG_TFMR(index)         (0x202 + (index))
@@ -204,15 +179,11 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
 #define W83795_REG_TSS(index)          (0x209 + (index))
 
 #define PWM_OUTPUT                     0
-#define PWM_START                      1
-#define PWM_NONSTOP                    2
-#define PWM_STOP_TIME                  3
-#define PWM_FREQ                       4
-#define W83795_REG_PWM(index, nr) \
-       (((nr) == 0 ? 0x210 : \
-         (nr) == 1 ? 0x220 : \
-         (nr) == 2 ? 0x228 : \
-         (nr) == 3 ? 0x230 : 0x218) + (index))
+#define PWM_FREQ                       1
+#define PWM_START                      2
+#define PWM_NONSTOP                    3
+#define PWM_STOP_TIME                  4
+#define W83795_REG_PWM(index, nr)      (0x210 + (nr) * 8 + (index))
 
 #define W83795_REG_FTSH(index)         (0x240 + (index) * 2)
 #define W83795_REG_FTSL(index)         (0x241 + (index) * 2)
@@ -251,7 +222,8 @@ static const u8 IN_LSB_SHIFT_IDX[][2] = {
 
 static inline u16 in_from_reg(u8 index, u16 val)
 {
-       if ((index >= REST_VLT_BEGIN) && (index <= REST_VLT_END))
+       /* 3VDD, 3VSB and VBAT: 6 mV/bit; other inputs: 2 mV/bit */
+       if (index >= 12 && index <= 14)
                return val * 6;
        else
                return val * 2;
@@ -259,7 +231,7 @@ static inline u16 in_from_reg(u8 index, u16 val)
 
 static inline u16 in_to_reg(u8 index, u16 val)
 {
-       if ((index >= REST_VLT_BEGIN) && (index <= REST_VLT_END))
+       if (index >= 12 && index <= 14)
                return val / 6;
        else
                return val / 2;
@@ -367,7 +339,7 @@ struct w83795_data {
        u8 has_temp;            /* Enable monitor temp6-1 or not */
        s8 temp[6][5];          /* current, crit, crit_hyst, warn, warn_hyst */
        u8 temp_read_vrlsb[6];
-       u8 temp_mode;           /* bit 0: TR mode, bit 1: TD mode */
+       u8 temp_mode;           /* Bit vector, 0 = TR, 1 = TD */
        u8 temp_src[3];         /* Register value */
 
        u8 enable_dts;          /* Enable PECI and SB-TSI,
@@ -381,8 +353,8 @@ struct w83795_data {
        u8 has_pwm;             /* 795g supports 8 pwm, 795adg only supports 2,
                                 * no config register, only affected by chip
                                 * type */
-       u8 pwm[8][5];           /* Register value, output, start, non stop, stop
-                                * time, freq */
+       u8 pwm[8][5];           /* Register value, output, freq, start,
+                                *  non stop, stop time */
        u16 clkin;              /* CLKIN frequency in kHz */
        u8 pwm_fcms[2];         /* Register value */
        u8 pwm_tfmr[6];         /* Register value */
@@ -400,6 +372,8 @@ struct w83795_data {
        u8 beeps[6];            /* Register value */
 
        char valid;
+       char valid_limits;
+       char valid_pwm_config;
 };
 
 /*
@@ -467,6 +441,137 @@ static int w83795_write(struct i2c_client *client, u16 reg, u8 value)
        return err;
 }
 
+static void w83795_update_limits(struct i2c_client *client)
+{
+       struct w83795_data *data = i2c_get_clientdata(client);
+       int i, limit;
+
+       /* Read the voltage limits */
+       for (i = 0; i < ARRAY_SIZE(data->in); i++) {
+               if (!(data->has_in & (1 << i)))
+                       continue;
+               data->in[i][IN_MAX] =
+                       w83795_read(client, W83795_REG_IN[i][IN_MAX]);
+               data->in[i][IN_LOW] =
+                       w83795_read(client, W83795_REG_IN[i][IN_LOW]);
+       }
+       for (i = 0; i < ARRAY_SIZE(data->in_lsb); i++) {
+               if ((i == 2 && data->chip_type == w83795adg) ||
+                   (i >= 4 && !(data->has_in & (1 << (i + 11)))))
+                       continue;
+               data->in_lsb[i][IN_MAX] =
+                       w83795_read(client, IN_LSB_REG(i, IN_MAX));
+               data->in_lsb[i][IN_LOW] =
+                       w83795_read(client, IN_LSB_REG(i, IN_LOW));
+       }
+
+       /* Read the fan limits */
+       for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
+               u8 lsb;
+
+               /* Each register contains LSB for 2 fans, but we want to
+                * read it only once to save time */
+               if ((i & 1) == 0 && (data->has_fan & (3 << i)))
+                       lsb = w83795_read(client, W83795_REG_FAN_MIN_LSB(i));
+
+               if (!(data->has_fan & (1 << i)))
+                       continue;
+               data->fan_min[i] =
+                       w83795_read(client, W83795_REG_FAN_MIN_HL(i)) << 4;
+               data->fan_min[i] |=
+                       (lsb >> W83795_REG_FAN_MIN_LSB_SHIFT(i)) & 0x0F;
+       }
+
+       /* Read the temperature limits */
+       for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+               if (!(data->has_temp & (1 << i)))
+                       continue;
+               for (limit = TEMP_CRIT; limit <= TEMP_WARN_HYST; limit++)
+                       data->temp[i][limit] =
+                               w83795_read(client, W83795_REG_TEMP[i][limit]);
+       }
+
+       /* Read the DTS limits */
+       if (data->enable_dts) {
+               for (limit = DTS_CRIT; limit <= DTS_WARN_HYST; limit++)
+                       data->dts_ext[limit] =
+                               w83795_read(client, W83795_REG_DTS_EXT(limit));
+       }
+
+       /* Read beep settings */
+       for (i = 0; i < ARRAY_SIZE(data->beeps); i++)
+               data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i));
+
+       data->valid_limits = 1;
+}
+
+static struct w83795_data *w83795_update_pwm_config(struct device *dev)
+{
+       struct i2c_client *client = to_i2c_client(dev);
+       struct w83795_data *data = i2c_get_clientdata(client);
+       int i, tmp;
+
+       mutex_lock(&data->update_lock);
+
+       if (data->valid_pwm_config)
+               goto END;
+
+       /* Read temperature source selection */
+       for (i = 0; i < ARRAY_SIZE(data->temp_src); i++)
+               data->temp_src[i] = w83795_read(client, W83795_REG_TSS(i));
+
+       /* Read automatic fan speed control settings */
+       data->pwm_fcms[0] = w83795_read(client, W83795_REG_FCMS1);
+       data->pwm_fcms[1] = w83795_read(client, W83795_REG_FCMS2);
+       for (i = 0; i < ARRAY_SIZE(data->pwm_tfmr); i++)
+               data->pwm_tfmr[i] = w83795_read(client, W83795_REG_TFMR(i));
+       data->pwm_fomc = w83795_read(client, W83795_REG_FOMC);
+       for (i = 0; i < data->has_pwm; i++) {
+               for (tmp = PWM_FREQ; tmp <= PWM_STOP_TIME; tmp++)
+                       data->pwm[i][tmp] =
+                               w83795_read(client, W83795_REG_PWM(i, tmp));
+       }
+       for (i = 0; i < ARRAY_SIZE(data->target_speed); i++) {
+               data->target_speed[i] =
+                       w83795_read(client, W83795_REG_FTSH(i)) << 4;
+               data->target_speed[i] |=
+                       w83795_read(client, W83795_REG_FTSL(i)) >> 4;
+       }
+       data->tol_speed = w83795_read(client, W83795_REG_TFTS) & 0x3f;
+
+       for (i = 0; i < ARRAY_SIZE(data->pwm_temp); i++) {
+               data->pwm_temp[i][TEMP_PWM_TTTI] =
+                       w83795_read(client, W83795_REG_TTTI(i)) & 0x7f;
+               data->pwm_temp[i][TEMP_PWM_CTFS] =
+                       w83795_read(client, W83795_REG_CTFS(i));
+               tmp = w83795_read(client, W83795_REG_HT(i));
+               data->pwm_temp[i][TEMP_PWM_HCT] = tmp >> 4;
+               data->pwm_temp[i][TEMP_PWM_HOT] = tmp & 0x0f;
+       }
+
+       /* Read SmartFanIV trip points */
+       for (i = 0; i < ARRAY_SIZE(data->sf4_reg); i++) {
+               for (tmp = 0; tmp < 7; tmp++) {
+                       data->sf4_reg[i][SF4_TEMP][tmp] =
+                               w83795_read(client,
+                                           W83795_REG_SF4_TEMP(i, tmp));
+                       data->sf4_reg[i][SF4_PWM][tmp] =
+                               w83795_read(client, W83795_REG_SF4_PWM(i, tmp));
+               }
+       }
+
+       /* Read setup PWM */
+       for (i = 0; i < ARRAY_SIZE(data->setup_pwm); i++)
+               data->setup_pwm[i] =
+                       w83795_read(client, W83795_REG_SETUP_PWM(i));
+
+       data->valid_pwm_config = 1;
+
+END:
+       mutex_unlock(&data->update_lock);
+       return data;
+}
+
 static struct w83795_data *w83795_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
@@ -476,6 +581,9 @@ static struct w83795_data *w83795_update_device(struct device *dev)
 
        mutex_lock(&data->update_lock);
 
+       if (!data->valid_limits)
+               w83795_update_limits(client);
+
        if (!(time_after(jiffies, data->last_updated + HZ * 2)
              || !data->valid))
                goto END;
@@ -485,8 +593,7 @@ static struct w83795_data *w83795_update_device(struct device *dev)
                if (!(data->has_in & (1 << i)))
                        continue;
                tmp = w83795_read(client, W83795_REG_IN[i][IN_READ]) << 2;
-               tmp |= (w83795_read(client, W83795_REG_VRLSB)
-                       >> VRLSB_SHIFT) & 0x03;
+               tmp |= w83795_read(client, W83795_REG_VRLSB) >> 6;
                data->in[i][IN_READ] = tmp;
        }
 
@@ -512,19 +619,11 @@ static struct w83795_data *w83795_update_device(struct device *dev)
                if (!(data->has_fan & (1 << i)))
                        continue;
                data->fan[i] = w83795_read(client, W83795_REG_FAN(i)) << 4;
-               data->fan[i] |=
-                 (w83795_read(client, W83795_REG_VRLSB) >> 4) & 0x0F;
+               data->fan[i] |= w83795_read(client, W83795_REG_VRLSB) >> 4;
        }
 
        /* Update temperature */
        for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-               /* even stop monitor, register still keep value, just read out
-                * it */
-               if (!(data->has_temp & (1 << i))) {
-                       data->temp[i][TEMP_READ] = 0;
-                       data->temp_read_vrlsb[i] = 0;
-                       continue;
-               }
                data->temp[i][TEMP_READ] =
                        w83795_read(client, W83795_REG_TEMP[i][TEMP_READ]);
                data->temp_read_vrlsb[i] =
@@ -532,7 +631,7 @@ static struct w83795_data *w83795_update_device(struct device *dev)
        }
 
        /* Update dts temperature */
-       if (data->enable_dts != 0) {
+       if (data->enable_dts) {
                for (i = 0; i < ARRAY_SIZE(data->dts); i++) {
                        if (!(data->has_dts & (1 << i)))
                                continue;
@@ -550,7 +649,7 @@ static struct w83795_data *w83795_update_device(struct device *dev)
        }
 
        /* update alarm */
-       for (i = 0; i < ALARM_BEEP_REG_NUM; i++)
+       for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
                data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
 
        data->last_updated = jiffies;
@@ -578,11 +677,10 @@ show_alarm_beep(struct device *dev, struct device_attribute *attr, char *buf)
        int bit = sensor_attr->index & 0x07;
        u8 val;
 
-       if (ALARM_STATUS == nr) {
-               val = (data->alarms[index] >> (bit)) & 1;
-       } else {                /* BEEP_ENABLE */
-               val = (data->beeps[index] >> (bit)) & 1;
-       }
+       if (nr == ALARM_STATUS)
+               val = (data->alarms[index] >> bit) & 1;
+       else            /* BEEP_ENABLE */
+               val = (data->beeps[index] >> bit) & 1;
 
        return sprintf(buf, "%u\n", val);
 }
@@ -615,7 +713,7 @@ store_beep(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-/* Write any value to clear chassis alarm */
+/* Write 0 to clear chassis alarm */
 static ssize_t
 store_chassis_clear(struct device *dev,
                    struct device_attribute *attr, const char *buf,
@@ -623,7 +721,10 @@ store_chassis_clear(struct device *dev,
 {
        struct i2c_client *client = to_i2c_client(dev);
        struct w83795_data *data = i2c_get_clientdata(client);
-       u8 val;
+       unsigned long val;
+
+       if (strict_strtoul(buf, 10, &val) < 0 || val != 0)
+               return -EINVAL;
 
        mutex_lock(&data->update_lock);
        val = w83795_read(client, W83795_REG_CLR_CHASSIS);
@@ -645,7 +746,7 @@ show_fan(struct device *dev, struct device_attribute *attr, char *buf)
        struct w83795_data *data = w83795_update_device(dev);
        u16 val;
 
-       if (FAN_INPUT == nr)
+       if (nr == FAN_INPUT)
                val = data->fan[index] & 0x0fff;
        else
                val = data->fan_min[index] & 0x0fff;
@@ -672,7 +773,7 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
        data->fan_min[index] = val;
        w83795_write(client, W83795_REG_FAN_MIN_HL(index), (val >> 4) & 0xff);
        val &= 0x0f;
-       if (index % 1) {
+       if (index & 1) {
                val <<= 4;
                val |= w83795_read(client, W83795_REG_FAN_MIN_LSB(index))
                       & 0x0f;
@@ -689,13 +790,16 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 static ssize_t
 show_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct w83795_data *data = w83795_update_device(dev);
+       struct w83795_data *data;
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
        int index = sensor_attr->index;
        unsigned int val;
 
+       data = nr == PWM_OUTPUT ? w83795_update_device(dev)
+                               : w83795_update_pwm_config(dev);
+
        switch (nr) {
        case PWM_STOP_TIME:
                val = time_from_reg(data->pwm[index][nr]);
@@ -749,8 +853,7 @@ show_pwm_enable(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        int index = sensor_attr->index;
        u8 tmp;
 
@@ -778,7 +881,7 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
          const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int index = sensor_attr->index;
@@ -819,13 +922,12 @@ show_temp_src(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        int index = sensor_attr->index;
        u8 val = index / 2;
        u8 tmp = data->temp_src[val];
 
-       if (index % 1)
+       if (index & 1)
                val = 4;
        else
                val = 0;
@@ -840,7 +942,7 @@ store_temp_src(struct device *dev, struct device_attribute *attr,
          const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int index = sensor_attr->index;
@@ -852,7 +954,7 @@ store_temp_src(struct device *dev, struct device_attribute *attr,
        tmp = SENSORS_LIMIT(tmp, 0, 15);
 
        mutex_lock(&data->update_lock);
-       if (index % 1) {
+       if (index & 1) {
                tmp <<= 4;
                data->temp_src[val] &= 0x0f;
        } else {
@@ -871,8 +973,7 @@ static ssize_t
 show_temp_pwm_enable(struct device *dev, struct device_attribute *attr,
                     char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
@@ -900,7 +1001,7 @@ store_temp_pwm_enable(struct device *dev, struct device_attribute *attr,
          const char *buf, size_t count)
 {
        struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
@@ -912,7 +1013,7 @@ store_temp_pwm_enable(struct device *dev, struct device_attribute *attr,
 
        switch (nr) {
        case TEMP_PWM_ENABLE:
-               if ((tmp != 3) && (tmp != 4))
+               if (tmp != 3 && tmp != 4)
                        return -EINVAL;
                tmp -= 3;
                mutex_lock(&data->update_lock);
@@ -937,8 +1038,7 @@ store_temp_pwm_enable(struct device *dev, struct device_attribute *attr,
 static ssize_t
 show_fanin(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
@@ -976,7 +1076,7 @@ store_fanin(struct device *dev, struct device_attribute *attr,
        switch (nr) {
        case FANIN_TARGET:
                val = fan_to_reg(SENSORS_LIMIT(val, 0, 0xfff));
-               w83795_write(client, W83795_REG_FTSH(index), (val >> 4) & 0xff);
+               w83795_write(client, W83795_REG_FTSH(index), val >> 4);
                w83795_write(client, W83795_REG_FTSL(index), (val << 4) & 0xf0);
                data->target_speed[index] = val;
                break;
@@ -995,8 +1095,7 @@ store_fanin(struct device *dev, struct device_attribute *attr,
 static ssize_t
 show_temp_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
@@ -1057,8 +1156,7 @@ store_temp_pwm(struct device *dev, struct device_attribute *attr,
 static ssize_t
 show_sf4_pwm(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
@@ -1093,8 +1191,7 @@ store_sf4_pwm(struct device *dev, struct device_attribute *attr,
 static ssize_t
 show_sf4_temp(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
@@ -1139,9 +1236,8 @@ show_temp(struct device *dev, struct device_attribute *attr, char *buf)
        struct w83795_data *data = w83795_update_device(dev);
        long temp = temp_from_reg(data->temp[index][nr]);
 
-       if (TEMP_READ == nr)
-               temp += ((data->temp_read_vrlsb[index] >> VRLSB_SHIFT) & 0x03)
-                       * 250;
+       if (nr == TEMP_READ)
+               temp += (data->temp_read_vrlsb[index] >> 6) * 250;
        return sprintf(buf, "%ld\n", temp);
 }
 
@@ -1171,24 +1267,13 @@ store_temp(struct device *dev, struct device_attribute *attr,
 static ssize_t
 show_dts_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
-       struct sensor_device_attribute_2 *sensor_attr =
-           to_sensor_dev_attr_2(attr);
-       int index = sensor_attr->index;
-       u8 tmp;
-
-       if (data->enable_dts == 0)
-               return sprintf(buf, "%d\n", 0);
+       struct w83795_data *data = dev_get_drvdata(dev);
+       int tmp;
 
-       if ((data->has_dts >> index) & 0x01) {
-               if (data->enable_dts & 2)
-                       tmp = 5;
-               else
-                       tmp = 6;
-       } else {
-               tmp = 0;
-       }
+       if (data->enable_dts & 2)
+               tmp = 5;
+       else
+               tmp = 6;
 
        return sprintf(buf, "%d\n", tmp);
 }
@@ -1202,7 +1287,7 @@ show_dts(struct device *dev, struct device_attribute *attr, char *buf)
        struct w83795_data *data = w83795_update_device(dev);
        long temp = temp_from_reg(data->dts[index]);
 
-       temp += ((data->dts_read_vrlsb[index] >> VRLSB_SHIFT) & 0x03) * 250;
+       temp += (data->dts_read_vrlsb[index] >> 6) * 250;
        return sprintf(buf, "%ld\n", temp);
 }
 
@@ -1212,8 +1297,7 @@ show_dts_ext(struct device *dev, struct device_attribute *attr, char *buf)
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = dev_get_drvdata(dev);
        long temp = temp_from_reg(data->dts_ext[nr]);
 
        return sprintf(buf, "%ld\n", temp);
@@ -1241,36 +1325,24 @@ store_dts_ext(struct device *dev, struct device_attribute *attr,
 }
 
 
-/*
-       Type 3:  Thermal diode
-       Type 4:  Thermistor
-
-       Temp5-6, default TR
-       Temp1-4, default TD
-*/
-
 static ssize_t
 show_temp_mode(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = dev_get_drvdata(dev);
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int index = sensor_attr->index;
-       u8 tmp;
+       int tmp;
 
-       if (data->has_temp >> index & 0x01) {
-               if (data->temp_mode >> index & 0x01)
-                       tmp = 3;
-               else
-                       tmp = 4;
-       } else {
-               tmp = 0;
-       }
+       if (data->temp_mode & (1 << index))
+               tmp = 3;        /* Thermal diode */
+       else
+               tmp = 4;        /* Thermistor */
 
        return sprintf(buf, "%d\n", tmp);
 }
 
+/* Only for temp1-4 (temp5-6 can only be thermistor) */
 static ssize_t
 store_temp_mode(struct device *dev, struct device_attribute *attr,
                const char *buf, size_t count)
@@ -1280,45 +1352,31 @@ store_temp_mode(struct device *dev, struct device_attribute *attr,
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int index = sensor_attr->index;
+       int reg_shift;
        unsigned long val;
        u8 tmp;
-       u32 mask;
 
        if (strict_strtoul(buf, 10, &val) < 0)
                return -EINVAL;
        if ((val != 4) && (val != 3))
                return -EINVAL;
-       if ((index > 3) && (val == 3))
-               return -EINVAL;
 
        mutex_lock(&data->update_lock);
        if (val == 3) {
-               val = TEMP_CTRL_TD;
-               data->has_temp |= 1 << index;
+               /* Thermal diode */
+               val = 0x01;
                data->temp_mode |= 1 << index;
        } else if (val == 4) {
-               val = TEMP_CTRL_TR;
-               data->has_temp |= 1 << index;
-               tmp = 1 << index;
-               data->temp_mode &= ~tmp;
+               /* Thermistor */
+               val = 0x03;
+               data->temp_mode &= ~(1 << index);
        }
 
-       if (index > 3)
-               tmp = w83795_read(client, W83795_REG_TEMP_CTRL1);
-       else
-               tmp = w83795_read(client, W83795_REG_TEMP_CTRL2);
-
-       mask = 0x03 << W83795_REG_TEMP_CTRL[index][TEMP_CTRL_SHIFT];
-       tmp &= ~mask;
-       tmp |= W83795_REG_TEMP_CTRL[index][val];
-
-       mask = 1 << W83795_REG_TEMP_CTRL[index][TEMP_CTRL_HASIN_SHIFT];
-       data->has_in &= ~mask;
-
-       if (index > 3)
-               w83795_write(client, W83795_REG_TEMP_CTRL1, tmp);
-       else
-               w83795_write(client, W83795_REG_TEMP_CTRL2, tmp);
+       reg_shift = 2 * index;
+       tmp = w83795_read(client, W83795_REG_TEMP_CTRL2);
+       tmp &= ~(0x03 << reg_shift);
+       tmp |= val << reg_shift;
+       w83795_write(client, W83795_REG_TEMP_CTRL2, tmp);
 
        mutex_unlock(&data->update_lock);
        return count;
@@ -1349,7 +1407,7 @@ show_in(struct device *dev, struct device_attribute *attr, char *buf)
                lsb_idx = IN_LSB_SHIFT_IDX[index][IN_LSB_IDX];
                val <<= 2;
                val |= (data->in_lsb[lsb_idx][nr] >>
-                       IN_LSB_SHIFT_IDX[lsb_idx][IN_LSB_SHIFT]) & 0x03;
+                       IN_LSB_SHIFT_IDX[index][IN_LSB_SHIFT]) & 0x03;
                if ((index >= 17) &&
                    !((data->has_gain >> (index - 17)) & 1))
                        val *= 8;
@@ -1400,14 +1458,14 @@ store_in(struct device *dev, struct device_attribute *attr,
 }
 
 
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
 static ssize_t
 show_sf_setup(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct sensor_device_attribute_2 *sensor_attr =
            to_sensor_dev_attr_2(attr);
        int nr = sensor_attr->nr;
-       struct i2c_client *client = to_i2c_client(dev);
-       struct w83795_data *data = i2c_get_clientdata(client);
+       struct w83795_data *data = w83795_update_pwm_config(dev);
        u16 val = data->setup_pwm[nr];
 
        switch (nr) {
@@ -1452,6 +1510,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
        mutex_unlock(&data->update_lock);
        return count;
 }
+#endif
 
 
 #define NOT_USED                       -1
@@ -1516,7 +1575,7 @@ store_sf_setup(struct device *dev, struct device_attribute *attr,
                show_alarm_beep, store_beep, BEEP_ENABLE, index + 17) }
 
 #define SENSOR_ATTR_TEMP(index) {                                      \
-       SENSOR_ATTR_2(temp##index##_type, S_IRUGO | S_IWUSR,            \
+       SENSOR_ATTR_2(temp##index##_type, S_IRUGO | (index < 4 ? S_IWUSR : 0), \
                show_temp_mode, store_temp_mode, NOT_USED, index - 1),  \
        SENSOR_ATTR_2(temp##index##_input, S_IRUGO, show_temp,          \
                NULL, TEMP_READ, index - 1),                            \
@@ -1653,10 +1712,13 @@ static const struct sensor_device_attribute_2 w83795_pwm[][7] = {
 };
 
 static const struct sensor_device_attribute_2 sda_single_files[] = {
-       SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
+       SENSOR_ATTR_2(intrusion0_alarm, S_IWUSR | S_IRUGO, show_alarm_beep,
                      store_chassis_clear, ALARM_STATUS, 46),
+       SENSOR_ATTR_2(intrusion0_beep, S_IWUSR | S_IRUGO, show_alarm_beep,
+                     store_beep, BEEP_ENABLE, 46),
        SENSOR_ATTR_2(beep_enable, S_IWUSR | S_IRUGO, show_alarm_beep,
                      store_beep, BEEP_ENABLE, 47),
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
        SENSOR_ATTR_2(speed_cruise_tolerance, S_IWUSR | S_IRUGO, show_fanin,
                store_fanin, FANIN_TOL, NOT_USED),
        SENSOR_ATTR_2(pwm_default, S_IWUSR | S_IRUGO, show_sf_setup,
@@ -1665,6 +1727,7 @@ static const struct sensor_device_attribute_2 sda_single_files[] = {
                      store_sf_setup, SETUP_PWM_UPTIME, NOT_USED),
        SENSOR_ATTR_2(pwm_downtime, S_IWUSR | S_IRUGO, show_sf_setup,
                      store_sf_setup, SETUP_PWM_DOWNTIME, NOT_USED),
+#endif
 };
 
 /*
@@ -1818,6 +1881,7 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
                        return err;
        }
 
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
        for (i = 0; i < data->has_pwm; i++) {
                for (j = 0; j < ARRAY_SIZE(w83795_pwm[0]); j++) {
                        err = fn(dev, &w83795_pwm[i][j].dev_attr);
@@ -1825,18 +1889,23 @@ static int w83795_handle_files(struct device *dev, int (*fn)(struct device *,
                                return err;
                }
        }
+#endif
 
        for (i = 0; i < ARRAY_SIZE(w83795_temp); i++) {
                if (!(data->has_temp & (1 << i)))
                        continue;
+#ifdef CONFIG_SENSORS_W83795_FANCTRL
                for (j = 0; j < ARRAY_SIZE(w83795_temp[0]); j++) {
+#else
+               for (j = 0; j < 8; j++) {
+#endif
                        err = fn(dev, &w83795_temp[i][j].dev_attr);
                        if (err)
                                return err;
                }
        }
 
-       if (data->enable_dts != 0) {
+       if (data->enable_dts) {
                for (i = 0; i < ARRAY_SIZE(w83795_dts); i++) {
                        if (!(data->has_dts & (1 << i)))
                                continue;
@@ -1972,143 +2041,13 @@ static int w83795_probe(struct i2c_client *client,
                }
        }
 
-       /* First update the voltages measured value and limits */
-       for (i = 0; i < ARRAY_SIZE(data->in); i++) {
-               if (!(data->has_in & (1 << i)))
-                       continue;
-               data->in[i][IN_MAX] =
-                       w83795_read(client, W83795_REG_IN[i][IN_MAX]);
-               data->in[i][IN_LOW] =
-                       w83795_read(client, W83795_REG_IN[i][IN_LOW]);
-               tmp = w83795_read(client, W83795_REG_IN[i][IN_READ]) << 2;
-               tmp |= (w83795_read(client, W83795_REG_VRLSB)
-                       >> VRLSB_SHIFT) & 0x03;
-               data->in[i][IN_READ] = tmp;
-       }
-       for (i = 0; i < IN_LSB_REG_NUM; i++) {
-               if ((i == 2 && data->chip_type == w83795adg) ||
-                   (i >= 4 && !(data->has_in & (1 << (i + 11)))))
-                       continue;
-               data->in_lsb[i][IN_MAX] =
-                       w83795_read(client, IN_LSB_REG(i, IN_MAX));
-               data->in_lsb[i][IN_LOW] =
-                       w83795_read(client, IN_LSB_REG(i, IN_LOW));
-       }
        data->has_gain = w83795_read(client, W83795_REG_VMIGB_CTRL) & 0x0f;
 
-       /* First update fan and limits */
-       for (i = 0; i < ARRAY_SIZE(data->fan); i++) {
-               /* Each register contains LSB for 2 fans, but we want to
-                * read it only once to save time */
-               if ((i & 1) == 0 && (data->has_fan & (3 << i)))
-                       tmp = w83795_read(client, W83795_REG_FAN_MIN_LSB(i));
-
-               if (!(data->has_fan & (1 << i)))
-                       continue;
-               data->fan_min[i] =
-                       w83795_read(client, W83795_REG_FAN_MIN_HL(i)) << 4;
-               data->fan_min[i] |=
-                       (tmp >> W83795_REG_FAN_MIN_LSB_SHIFT(i)) & 0x0F;
-               data->fan[i] = w83795_read(client, W83795_REG_FAN(i)) << 4;
-               data->fan[i] |=
-                 (w83795_read(client, W83795_REG_VRLSB) >> 4) & 0x0F;
-       }
-
-       /* temperature and limits */
-       for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
-               if (!(data->has_temp & (1 << i)))
-                       continue;
-               data->temp[i][TEMP_CRIT] =
-                       w83795_read(client, W83795_REG_TEMP[i][TEMP_CRIT]);
-               data->temp[i][TEMP_CRIT_HYST] =
-                       w83795_read(client, W83795_REG_TEMP[i][TEMP_CRIT_HYST]);
-               data->temp[i][TEMP_WARN] =
-                       w83795_read(client, W83795_REG_TEMP[i][TEMP_WARN]);
-               data->temp[i][TEMP_WARN_HYST] =
-                       w83795_read(client, W83795_REG_TEMP[i][TEMP_WARN_HYST]);
-               data->temp[i][TEMP_READ] =
-                       w83795_read(client, W83795_REG_TEMP[i][TEMP_READ]);
-               data->temp_read_vrlsb[i] =
-                       w83795_read(client, W83795_REG_VRLSB);
-       }
-
-       /* dts temperature and limits */
-       if (data->enable_dts != 0) {
-               data->dts_ext[DTS_CRIT] =
-                       w83795_read(client, W83795_REG_DTS_EXT(DTS_CRIT));
-               data->dts_ext[DTS_CRIT_HYST] =
-                       w83795_read(client, W83795_REG_DTS_EXT(DTS_CRIT_HYST));
-               data->dts_ext[DTS_WARN] =
-                       w83795_read(client, W83795_REG_DTS_EXT(DTS_WARN));
-               data->dts_ext[DTS_WARN_HYST] =
-                       w83795_read(client, W83795_REG_DTS_EXT(DTS_WARN_HYST));
-               for (i = 0; i < ARRAY_SIZE(data->dts); i++) {
-                       if (!(data->has_dts & (1 << i)))
-                               continue;
-                       data->dts[i] = w83795_read(client, W83795_REG_DTS(i));
-                       data->dts_read_vrlsb[i] =
-                               w83795_read(client, W83795_REG_VRLSB);
-               }
-       }
-
-       /* First update temp source selction */
-       for (i = 0; i < 3; i++)
-               data->temp_src[i] = w83795_read(client, W83795_REG_TSS(i));
-
        /* pwm and smart fan */
        if (data->chip_type == w83795g)
                data->has_pwm = 8;
        else
                data->has_pwm = 2;
-       data->pwm_fcms[0] = w83795_read(client, W83795_REG_FCMS1);
-       data->pwm_fcms[1] = w83795_read(client, W83795_REG_FCMS2);
-       for (i = 0; i < W83795_REG_TEMP_NUM; i++)
-               data->pwm_tfmr[i] = w83795_read(client, W83795_REG_TFMR(i));
-       data->pwm_fomc = w83795_read(client, W83795_REG_FOMC);
-       for (i = 0; i < data->has_pwm; i++) {
-               for (tmp = 0; tmp < 5; tmp++) {
-                       data->pwm[i][tmp] =
-                               w83795_read(client, W83795_REG_PWM(i, tmp));
-               }
-       }
-       for (i = 0; i < 8; i++) {
-               data->target_speed[i] =
-                       w83795_read(client, W83795_REG_FTSH(i)) << 4;
-               data->target_speed[i] |=
-                       w83795_read(client, W83795_REG_FTSL(i)) >> 4;
-       }
-       data->tol_speed = w83795_read(client, W83795_REG_TFTS) & 0x3f;
-
-       for (i = 0; i < W83795_REG_TEMP_NUM; i++) {
-               data->pwm_temp[i][TEMP_PWM_TTTI] =
-                       w83795_read(client, W83795_REG_TTTI(i)) & 0x7f;
-               data->pwm_temp[i][TEMP_PWM_CTFS] =
-                       w83795_read(client, W83795_REG_CTFS(i));
-               tmp = w83795_read(client, W83795_REG_HT(i));
-               data->pwm_temp[i][TEMP_PWM_HCT] = (tmp >> 4) & 0x0f;
-               data->pwm_temp[i][TEMP_PWM_HOT] = tmp & 0x0f;
-       }
-       for (i = 0; i < W83795_REG_TEMP_NUM; i++) {
-               for (tmp = 0; tmp < 7; tmp++) {
-                       data->sf4_reg[i][SF4_TEMP][tmp] =
-                               w83795_read(client,
-                                           W83795_REG_SF4_TEMP(i, tmp));
-                       data->sf4_reg[i][SF4_PWM][tmp] =
-                               w83795_read(client, W83795_REG_SF4_PWM(i, tmp));
-               }
-       }
-
-       /* Setup PWM Register */
-       for (i = 0; i < 3; i++) {
-               data->setup_pwm[i] =
-                       w83795_read(client, W83795_REG_SETUP_PWM(i));
-       }
-
-       /* alarm and beep */
-       for (i = 0; i < ALARM_BEEP_REG_NUM; i++) {
-               data->alarms[i] = w83795_read(client, W83795_REG_ALARM(i));
-               data->beeps[i] = w83795_read(client, W83795_REG_BEEP(i));
-       }
 
        err = w83795_handle_files(dev, device_create_file);
        if (err)
@@ -2174,7 +2113,7 @@ static void __exit sensors_w83795_exit(void)
        i2c_del_driver(&w83795_driver);
 }
 
-MODULE_AUTHOR("Wei Song");
+MODULE_AUTHOR("Wei Song, Jean Delvare <khali@linux-fr.org>");
 MODULE_DESCRIPTION("W83795G/ADG hardware monitoring driver");
 MODULE_LICENSE("GPL");