hwmon: (abituguru3) Add AUX4 fan input for Abit IP35 Pro
[powerpc.git] / drivers / hwmon / lm90.c
index af541d6..f7ec95b 100644 (file)
@@ -41,7 +41,8 @@
  *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2578
  * Note that there is no easy way to differentiate between the three
  * variants. The extra address and features of the MAX6659 are not
- * supported by this driver.
+ * supported by this driver. These chips lack the remote temperature
+ * offset feature.
  *
  * This driver also supports the MAX6680 and MAX6681, two other sensor
  * chips made by Maxim. These are quite similar to the other Maxim
@@ -203,7 +204,6 @@ static struct i2c_driver lm90_driver = {
        .driver = {
                .name   = "lm90",
        },
-       .id             = I2C_DRIVERID_LM90,
        .attach_adapter = lm90_attach_adapter,
        .detach_client  = lm90_detach_client,
 };
@@ -214,7 +214,7 @@ static struct i2c_driver lm90_driver = {
 
 struct lm90_data {
        struct i2c_client client;
-       struct class_device *class_dev;
+       struct device *hwmon_dev;
        struct mutex update_lock;
        char valid; /* zero until following fields are valid */
        unsigned long last_updated; /* in jiffies */
@@ -226,9 +226,10 @@ struct lm90_data {
                           2: local high limit
                           3: local critical limit
                           4: remote critical limit */
-       s16 temp11[3];  /* 0: remote input
+       s16 temp11[4];  /* 0: remote input
                           1: remote low limit
-                          2: remote high limit */
+                          2: remote high limit
+                          3: remote offset (except max6657) */
        u8 temp_hyst;
        u8 alarms; /* bitvector */
 };
@@ -282,11 +283,13 @@ static ssize_t show_temp11(struct device *dev, struct device_attribute *devattr,
 static ssize_t set_temp11(struct device *dev, struct device_attribute *devattr,
                          const char *buf, size_t count)
 {
-       static const u8 reg[4] = {
+       static const u8 reg[6] = {
                LM90_REG_W_REMOTE_LOWH,
                LM90_REG_W_REMOTE_LOWL,
                LM90_REG_W_REMOTE_HIGHH,
                LM90_REG_W_REMOTE_HIGHL,
+               LM90_REG_W_REMOTE_OFFSH,
+               LM90_REG_W_REMOTE_OFFSL,
        };
 
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
@@ -367,6 +370,8 @@ static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp8,
 static SENSOR_DEVICE_ATTR(temp1_crit_hyst, S_IWUSR | S_IRUGO, show_temphyst,
        set_temphyst, 3);
 static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp2_offset, S_IWUSR | S_IRUGO, show_temp11,
+       set_temp11, 3);
 
 /* Individual alarm files */
 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
@@ -525,24 +530,24 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
                kind = lm90;
 
        if (kind < 0) { /* detection and identification */
-               u8 man_id, chip_id, reg_config1, reg_convrate;
-
-               if (lm90_read_reg(new_client, LM90_REG_R_MAN_ID,
-                                 &man_id) < 0
-                || lm90_read_reg(new_client, LM90_REG_R_CHIP_ID,
-                                 &chip_id) < 0
-                || lm90_read_reg(new_client, LM90_REG_R_CONFIG1,
-                                 &reg_config1) < 0
-                || lm90_read_reg(new_client, LM90_REG_R_CONVRATE,
-                                 &reg_convrate) < 0)
+               int man_id, chip_id, reg_config1, reg_convrate;
+
+               if ((man_id = i2c_smbus_read_byte_data(new_client,
+                                               LM90_REG_R_MAN_ID)) < 0
+                || (chip_id = i2c_smbus_read_byte_data(new_client,
+                                               LM90_REG_R_CHIP_ID)) < 0
+                || (reg_config1 = i2c_smbus_read_byte_data(new_client,
+                                               LM90_REG_R_CONFIG1)) < 0
+                || (reg_convrate = i2c_smbus_read_byte_data(new_client,
+                                               LM90_REG_R_CONVRATE)) < 0)
                        goto exit_free;
                
                if ((address == 0x4C || address == 0x4D)
                 && man_id == 0x01) { /* National Semiconductor */
-                       u8 reg_config2;
+                       int reg_config2;
 
-                       if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
-                                         &reg_config2) < 0)
+                       if ((reg_config2 = i2c_smbus_read_byte_data(new_client,
+                                               LM90_REG_R_CONFIG2)) < 0)
                                goto exit_free;
 
                        if ((reg_config1 & 0x2A) == 0x00
@@ -652,10 +657,15 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
                                              &dev_attr_pec)))
                        goto exit_remove_files;
        }
+       if (data->kind != max6657) {
+               if ((err = device_create_file(&new_client->dev,
+                               &sensor_dev_attr_temp2_offset.dev_attr)))
+                       goto exit_remove_files;
+       }
 
-       data->class_dev = hwmon_device_register(&new_client->dev);
-       if (IS_ERR(data->class_dev)) {
-               err = PTR_ERR(data->class_dev);
+       data->hwmon_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->hwmon_dev)) {
+               err = PTR_ERR(data->hwmon_dev);
                goto exit_remove_files;
        }
 
@@ -707,9 +717,12 @@ static int lm90_detach_client(struct i2c_client *client)
        struct lm90_data *data = i2c_get_clientdata(client);
        int err;
 
-       hwmon_device_unregister(data->class_dev);
+       hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&client->dev.kobj, &lm90_group);
        device_remove_file(&client->dev, &dev_attr_pec);
+       if (data->kind != max6657)
+               device_remove_file(&client->dev,
+                                  &sensor_dev_attr_temp2_offset.dev_attr);
 
        if ((err = i2c_detach_client(client)))
                return err;
@@ -763,6 +776,13 @@ static struct lm90_data *lm90_update_device(struct device *dev)
                if (lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHH, &newh) == 0
                 && lm90_read_reg(client, LM90_REG_R_REMOTE_HIGHL, &l) == 0)
                        data->temp11[2] = (newh << 8) | l;
+               if (data->kind != max6657) {
+                       if (lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSH,
+                                         &newh) == 0
+                        && lm90_read_reg(client, LM90_REG_R_REMOTE_OFFSL,
+                                         &l) == 0)
+                               data->temp11[3] = (newh << 8) | l;
+               }
                lm90_read_reg(client, LM90_REG_R_STATUS, &data->alarms);
 
                data->last_updated = jiffies;