]> err.no Git - linux-2.6/blobdiff - drivers/hwmon/w83793.c
Merge branch 'nfs-server-stable' of git://linux-nfs.org/~bfields/linux
[linux-2.6] / drivers / hwmon / w83793.c
index c2b7834ecaa96613984411c687bdd619fd86180e..48599e1cc554a829826939cc0285bbe58d1a751a 100644 (file)
@@ -179,7 +179,7 @@ static inline s8 TEMP_TO_REG(long val, s8 min, s8 max)
 struct w83793_data {
        struct i2c_client client;
        struct i2c_client *lm75[2];
-       struct class_device *class_dev;
+       struct device *hwmon_dev;
        struct mutex update_lock;
        char valid;                     /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
@@ -205,6 +205,7 @@ struct w83793_data {
 
        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 */
@@ -1025,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,
@@ -1071,7 +1075,7 @@ static int w83793_detach_client(struct i2c_client *client)
 
        /* main client */
        if (data) {
-               hwmon_device_unregister(data->class_dev);
+               hwmon_device_unregister(data->hwmon_dev);
 
                for (i = 0; i < ARRAY_SIZE(w83793_sensor_attr_2); i++)
                        device_remove_file(dev,
@@ -1080,6 +1084,9 @@ 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);
 
@@ -1327,6 +1334,20 @@ 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)
@@ -1344,6 +1365,13 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
        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,
@@ -1352,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)
@@ -1398,9 +1434,9 @@ static int w83793_detect(struct i2c_adapter *adapter, int address, int kind)
                }
        }
 
-       data->class_dev = hwmon_device_register(dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       data->hwmon_dev = hwmon_device_register(dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
                goto exit_remove;
        }
 
@@ -1415,6 +1451,9 @@ 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);
 
@@ -1579,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;