]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/hwmon/lm85.c
[MIPS] Alchemy: move UART platform code to its proper place
[linux-2.6-omap-h63xx.git] / drivers / hwmon / lm85.c
index 3b70815ab982d1d39688fb55cdd9adb51a635e17..182fe6a5605f9f7c64954f21c6ec3ecf88cb1aa7 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/mutex.h>
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
 
 /* Insmod parameters */
 I2C_CLIENT_INSMOD_6(lm85b, lm85c, adm1027, adt7463, emc6d100, emc6d102);
@@ -139,22 +139,26 @@ static int lm85_scaling[] = {  /* .001 Volts */
 #define INS_TO_REG(n,val)      \
                SENSORS_LIMIT(SCALE(val,lm85_scaling[n],192),0,255)
 
-#define INSEXT_FROM_REG(n,val,ext,scale)       \
-               SCALE((val)*(scale) + (ext),192*(scale),lm85_scaling[n])
+#define INSEXT_FROM_REG(n,val,ext)     \
+               SCALE(((val) << 4) + (ext), 192 << 4, lm85_scaling[n])
 
-#define INS_FROM_REG(n,val)   INSEXT_FROM_REG(n,val,0,1)
+#define INS_FROM_REG(n,val)    SCALE((val), 192, lm85_scaling[n])
 
 /* FAN speed is measured using 90kHz clock */
-#define FAN_TO_REG(val)                (SENSORS_LIMIT( (val)<=0?0: 5400000/(val),0,65534))
+static inline u16 FAN_TO_REG(unsigned long val)
+{
+       if (!val)
+               return 0xffff;
+       return SENSORS_LIMIT(5400000 / val, 1, 0xfffe);
+}
 #define FAN_FROM_REG(val)      ((val)==0?-1:(val)==0xffff?0:5400000/(val))
 
 /* Temperature is reported in .001 degC increments */
 #define TEMP_TO_REG(val)       \
                SENSORS_LIMIT(SCALE(val,1000,1),-127,127)
-#define TEMPEXT_FROM_REG(val,ext,scale)        \
-               SCALE((val)*scale + (ext),scale,1000)
-#define TEMP_FROM_REG(val)     \
-               TEMPEXT_FROM_REG(val,0,1)
+#define TEMPEXT_FROM_REG(val,ext)      \
+               SCALE(((val) << 4) + (ext), 16, 1000)
+#define TEMP_FROM_REG(val)     ((val) * 1000)
 
 #define PWM_TO_REG(val)                        (SENSORS_LIMIT(val,0,255))
 #define PWM_FROM_REG(val)              (val)
@@ -334,7 +338,6 @@ struct lm85_data {
        u8 tach_mode;           /* Register encoding, combined */
        u8 temp_ext[3];         /* Decoded values */
        u8 in_ext[8];           /* Decoded values */
-       u8 adc_scale;           /* ADC Extended bits scaling factor */
        u8 fan_ppr;             /* Register value */
        u8 smooth[3];           /* Register encoding */
        u8 vid;                 /* Register value */
@@ -364,7 +367,6 @@ static struct i2c_driver lm85_driver = {
        .driver = {
                .name   = "lm85",
        },
-       .id             = I2C_DRIVERID_LM85,
        .attach_adapter = lm85_attach_adapter,
        .detach_client  = lm85_detach_client,
 };
@@ -393,7 +395,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
        int nr = to_sensor_dev_attr(attr)->index;
        struct i2c_client *client = to_i2c_client(dev);
        struct lm85_data *data = i2c_get_clientdata(client);
-       long val = simple_strtol(buf, NULL, 10);
+       unsigned long val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
        data->fan_min[nr] = FAN_TO_REG(val);
@@ -435,18 +437,14 @@ static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
 static ssize_t show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 {
-       struct lm85_data *data = lm85_update_device(dev);
+       struct lm85_data *data = dev_get_drvdata(dev);
        return sprintf(buf, "%ld\n", (long) data->vrm);
 }
 
 static ssize_t store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-       struct i2c_client *client = to_i2c_client(dev);
-       struct lm85_data *data = i2c_get_clientdata(client);
-       u32 val;
-
-       val = simple_strtoul(buf, NULL, 10);
-       data->vrm = val;
+       struct lm85_data *data = dev_get_drvdata(dev);
+       data->vrm = simple_strtoul(buf, NULL, 10);
        return count;
 }
 
@@ -516,17 +514,64 @@ static ssize_t show_pwm_enable(struct device *dev, struct device_attribute
 {
        int nr = to_sensor_dev_attr(attr)->index;
        struct lm85_data *data = lm85_update_device(dev);
-       int     pwm_zone;
+       int pwm_zone, enable;
 
        pwm_zone = ZONE_FROM_REG(data->autofan[nr].config);
-       return sprintf(buf,"%d\n", (pwm_zone != 0 && pwm_zone != -1) );
+       switch (pwm_zone) {
+       case -1:        /* PWM is always at 100% */
+               enable = 0;
+               break;
+       case 0:         /* PWM is always at 0% */
+       case -2:        /* PWM responds to manual control */
+               enable = 1;
+               break;
+       default:        /* PWM in automatic mode */
+               enable = 2;
+       }
+       return sprintf(buf, "%d\n", enable);
+}
+
+static ssize_t set_pwm_enable(struct device *dev, struct device_attribute
+               *attr, const char *buf, size_t count)
+{
+       int nr = to_sensor_dev_attr(attr)->index;
+       struct i2c_client *client = to_i2c_client(dev);
+       struct lm85_data *data = i2c_get_clientdata(client);
+       long val = simple_strtol(buf, NULL, 10);
+       u8 config;
+
+       switch (val) {
+       case 0:
+               config = 3;
+               break;
+       case 1:
+               config = 7;
+               break;
+       case 2:
+               /* Here we have to choose arbitrarily one of the 5 possible
+                  configurations; I go for the safest */
+               config = 6;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       mutex_lock(&data->update_lock);
+       data->autofan[nr].config = lm85_read_value(client,
+               LM85_REG_AFAN_CONFIG(nr));
+       data->autofan[nr].config = (data->autofan[nr].config & ~0xe0)
+               | (config << 5);
+       lm85_write_value(client, LM85_REG_AFAN_CONFIG(nr),
+               data->autofan[nr].config);
+       mutex_unlock(&data->update_lock);
+       return count;
 }
 
 #define show_pwm_reg(offset)                                           \
 static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,              \
                show_pwm, set_pwm, offset - 1);                         \
-static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO,               \
-               show_pwm_enable, NULL, offset - 1)
+static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,     \
+               show_pwm_enable, set_pwm_enable, offset - 1)
 
 show_pwm_reg(1);
 show_pwm_reg(2);
@@ -541,8 +586,7 @@ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
        struct lm85_data *data = lm85_update_device(dev);
        return sprintf( buf, "%d\n", INSEXT_FROM_REG(nr,
                                                     data->in[nr],
-                                                    data->in_ext[nr],
-                                                    data->adc_scale) );
+                                                    data->in_ext[nr]));
 }
 
 static ssize_t show_in_min(struct device *dev,  struct device_attribute *attr,
@@ -616,8 +660,7 @@ static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
        int nr = to_sensor_dev_attr(attr)->index;
        struct lm85_data *data = lm85_update_device(dev);
        return sprintf(buf,"%d\n", TEMPEXT_FROM_REG(data->temp[nr],
-                                                   data->temp_ext[nr],
-                                                   data->adc_scale) );
+                                                   data->temp_ext[nr]));
 }
 
 static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
@@ -1394,6 +1437,8 @@ static struct lm85_data *lm85_update_device(struct device *dev)
                
                /* Have to read extended bits first to "freeze" the
                 * more significant bits that are read later.
+                * There are 2 additional resolution bits per channel and we
+                * have room for 4, so we shift them to the left.
                 */
                if ( (data->type == adm1027) || (data->type == adt7463) ) {
                        int ext1 = lm85_read_value(client,
@@ -1403,18 +1448,12 @@ static struct lm85_data *lm85_update_device(struct device *dev)
                        int val = (ext1 << 8) + ext2;
 
                        for(i = 0; i <= 4; i++)
-                               data->in_ext[i] = (val>>(i * 2))&0x03;
+                               data->in_ext[i] = ((val>>(i * 2))&0x03) << 2;
 
                        for(i = 0; i <= 2; i++)
-                               data->temp_ext[i] = (val>>((i + 5) * 2))&0x03;
+                               data->temp_ext[i] = (val>>((i + 4) * 2))&0x0c;
                }
 
-               /* adc_scale is 2^(number of LSBs). There are 4 extra bits in
-                  the emc6d102 and 2 in the adt7463 and adm1027. In all
-                  other chips ext is always 0 and the value of scale is
-                  irrelevant. So it is left in 4*/
-               data->adc_scale = (data->type == emc6d102 ) ? 16 : 4;
-
                data->vid = lm85_read_value(client, LM85_REG_VID);
 
                for (i = 0; i <= 3; ++i) {