]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/hwmon/w83793.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/sam/kbuild-fix
[linux-2.6-omap-h63xx.git] / drivers / hwmon / w83793.c
index 99e603a6a667dfd12fe8d35fb54a8bc28b860022..253ffaf1568a7baefdeb86468b3467ae23d5466c 100644 (file)
@@ -204,6 +204,8 @@ struct w83793_data {
        u8 temp_fan_map[6];     /* Temp controls which pwm fan, bit field */
 
        u8 has_pwm;
+       u8 has_temp;
+       u8 has_vid;
        u8 pwm_enable;          /* Register value, each Temp has 1 bit */
        u8 pwm_uptime;          /* Register value */
        u8 pwm_downtime;        /* Register value */
@@ -554,8 +556,7 @@ store_temp_mode(struct device *dev, struct device_attribute *attr,
        if ((val == 6) && (index < 4)) {
                val -= 3;
        } else if ((val == 3 && index < 4)
-               || (val == 4 && index >= 4)
-               || val == 0) {
+               || (val == 4 && index >= 4)) {
                /* transform diode or thermistor into internal enable */
                val = !!val;
        } else {
@@ -986,12 +987,6 @@ static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
        SENSOR_ATTR_IN(7),
        SENSOR_ATTR_IN(8),
        SENSOR_ATTR_IN(9),
-       SENSOR_ATTR_TEMP(1),
-       SENSOR_ATTR_TEMP(2),
-       SENSOR_ATTR_TEMP(3),
-       SENSOR_ATTR_TEMP(4),
-       SENSOR_ATTR_TEMP(5),
-       SENSOR_ATTR_TEMP(6),
        SENSOR_ATTR_FAN(1),
        SENSOR_ATTR_FAN(2),
        SENSOR_ATTR_FAN(3),
@@ -1002,6 +997,15 @@ static struct sensor_device_attribute_2 w83793_sensor_attr_2[] = {
        SENSOR_ATTR_PWM(3),
 };
 
+static struct sensor_device_attribute_2 w83793_temp[] = {
+       SENSOR_ATTR_TEMP(1),
+       SENSOR_ATTR_TEMP(2),
+       SENSOR_ATTR_TEMP(3),
+       SENSOR_ATTR_TEMP(4),
+       SENSOR_ATTR_TEMP(5),
+       SENSOR_ATTR_TEMP(6),
+};
+
 /* Fan6-Fan12 */
 static struct sensor_device_attribute_2 w83793_left_fan[] = {
        SENSOR_ATTR_FAN(6),
@@ -1022,9 +1026,12 @@ static struct sensor_device_attribute_2 w83793_left_pwm[] = {
        SENSOR_ATTR_PWM(8),
 };
 
-static struct sensor_device_attribute_2 sda_single_files[] = {
+static struct sensor_device_attribute_2 w83793_vid[] = {
        SENSOR_ATTR_2(cpu0_vid, S_IRUGO, show_vid, NULL, NOT_USED, 0),
        SENSOR_ATTR_2(cpu1_vid, S_IRUGO, show_vid, NULL, NOT_USED, 1),
+};
+
+static struct sensor_device_attribute_2 sda_single_files[] = {
        SENSOR_ATTR_2(vrm, S_IWUSR | S_IRUGO, show_vrm, store_vrm,
                      NOT_USED, NOT_USED),
        SENSOR_ATTR_2(chassis, S_IWUSR | S_IRUGO, show_alarm_beep,
@@ -1077,11 +1084,17 @@ static int w83793_detach_client(struct i2c_client *client)
                for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
                        device_remove_file(dev, &sda_single_files[i].dev_attr);
 
+               for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+                       device_remove_file(dev, &w83793_vid[i].dev_attr);
+
                for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
                        device_remove_file(dev, &w83793_left_fan[i].dev_attr);
 
                for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
                        device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
+
+               for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+                       device_remove_file(dev, &w83793_temp[i].dev_attr);
        }
 
        if ((err = i2c_detach_client(client)))
@@ -1194,6 +1207,7 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
        struct w83793_data *data;
        int files_fan = ARRAY_SIZE(w83793_left_fan) / 7;
        int files_pwm = ARRAY_SIZE(w83793_left_pwm) / 5;
+       int files_temp = ARRAY_SIZE(w83793_temp) / 6;
        int err = 0;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
@@ -1320,6 +1334,44 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
                data->has_pwm |= 0x80;
        }
 
+       tmp = w83793_read_value(client, W83793_REG_FANIN_SEL);
+       if ((tmp & 0x01) && (val & 0x08)) {     /* fan 9, second location */
+               data->has_fan |= 0x100;
+       }
+       if ((tmp & 0x02) && (val & 0x10)) {     /* fan 10, second location */
+               data->has_fan |= 0x200;
+       }
+       if ((tmp & 0x04) && (val & 0x20)) {     /* fan 11, second location */
+               data->has_fan |= 0x400;
+       }
+       if ((tmp & 0x08) && (val & 0x40)) {     /* fan 12, second location */
+               data->has_fan |= 0x800;
+       }
+
+       /* check the temp1-6 mode, ignore former AMDSI selected inputs */
+       tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[0]);
+       if (tmp & 0x01)
+               data->has_temp |= 0x01;
+       if (tmp & 0x04)
+               data->has_temp |= 0x02;
+       if (tmp & 0x10)
+               data->has_temp |= 0x04;
+       if (tmp & 0x40)
+               data->has_temp |= 0x08;
+
+       tmp = w83793_read_value(client,W83793_REG_TEMP_MODE[1]);
+       if (tmp & 0x01)
+               data->has_temp |= 0x10;
+       if (tmp & 0x02)
+               data->has_temp |= 0x20;
+
+       /* Detect the VID usage and ignore unused input */
+       tmp = w83793_read_value(client, W83793_REG_MFC);
+       if (!(tmp & 0x29))
+               data->has_vid |= 0x1;   /* has VIDA */
+       if (tmp & 0x80)
+               data->has_vid |= 0x2;   /* has VIDB */
+
        /* Register sysfs hooks */
        for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++) {
                err = device_create_file(dev,
@@ -1328,6 +1380,14 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
                        goto exit_remove;
        }
 
+       for (i = 0; i < ARRAY_SIZE(w83793_vid); i++) {
+               if (!(data->has_vid & (1 << i)))
+                       continue;
+               err = device_create_file(dev, &w83793_vid[i].dev_attr);
+               if (err)
+                       goto exit_remove;
+       }
+
        for (i = 0; i < ARRAY_SIZE(sda_single_files); i++) {
                err = device_create_file(dev, &sda_single_files[i].dev_attr);
                if (err)
@@ -1335,6 +1395,19 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
 
        }
 
+       for (i = 0; i < 6; i++) {
+               int j;
+               if (!(data->has_temp & (1 << i)))
+                       continue;
+               for (j = 0; j < files_temp; j++) {
+                       err = device_create_file(dev,
+                                               &w83793_temp[(i) * files_temp
+                                                               + j].dev_attr);
+                       if (err)
+                               goto exit_remove;
+               }
+       }
+
        for (i = 5; i < 12; i++) {
                int j;
                if (!(data->has_fan & (1 << i)))
@@ -1378,12 +1451,18 @@ exit_remove:
        for (i = 0; i < ARRAY_SIZE(sda_single_files); i++)
                device_remove_file(dev, &sda_single_files[i].dev_attr);
 
+       for (i = 0; i < ARRAY_SIZE(w83793_vid); i++)
+               device_remove_file(dev, &w83793_vid[i].dev_attr);
+
        for (i = 0; i < ARRAY_SIZE(w83793_left_fan); i++)
                device_remove_file(dev, &w83793_left_fan[i].dev_attr);
 
        for (i = 0; i < ARRAY_SIZE(w83793_left_pwm); i++)
                device_remove_file(dev, &w83793_left_pwm[i].dev_attr);
 
+       for (i = 0; i < ARRAY_SIZE(w83793_temp); i++)
+               device_remove_file(dev, &w83793_temp[i].dev_attr);
+
        if (data->lm75[0] != NULL) {
                i2c_detach_client(data->lm75[0]);
                kfree(data->lm75[0]);
@@ -1435,6 +1514,8 @@ static void w83793_update_nonvolatile(struct device *dev)
        }
 
        for (i = 0; i < ARRAY_SIZE(data->temp_fan_map); i++) {
+               if (!(data->has_temp & (1 << i)))
+                       continue;
                data->temp_fan_map[i] =
                    w83793_read_value(client, W83793_REG_TEMP_FAN_MAP(i));
                for (j = 1; j < 5; j++) {
@@ -1517,9 +1598,12 @@ static struct w83793_data *w83793_update_device(struct device *dev)
                    w83793_read_value(client, W83793_REG_FAN(i) + 1);
        }
 
-       for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+       for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+               if (!(data->has_temp & (1 << i)))
+                       continue;
                data->temp[i][TEMP_READ] =
                    w83793_read_value(client, W83793_REG_TEMP[i][TEMP_READ]);
+       }
 
        data->temp_low_bits =
            w83793_read_value(client, W83793_REG_TEMP_LOW_BITS);
@@ -1534,8 +1618,10 @@ static struct w83793_data *w83793_update_device(struct device *dev)
        for (i = 0; i < ARRAY_SIZE(data->alarms); i++)
                data->alarms[i] =
                    w83793_read_value(client, W83793_REG_ALARM(i));
-       data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
-       data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
+       if (data->has_vid & 0x01)
+               data->vid[0] = w83793_read_value(client, W83793_REG_VID_INA);
+       if (data->has_vid & 0x02)
+               data->vid[1] = w83793_read_value(client, W83793_REG_VID_INB);
        w83793_update_nonvolatile(dev);
        data->last_updated = jiffies;
        data->valid = 1;