]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/hwmon/w83781d.c
hwmon: (w83781d) Refactor beep enable handling
[linux-2.6-omap-h63xx.git] / drivers / hwmon / w83781d.c
index e0fa7520400d8c565f0b7c77034a6c0e35cf4a1a..136bec3fd64542f952e7325c17805ac306249e3a 100644 (file)
@@ -28,7 +28,6 @@
     as99127f   7       3       0       3       0x31    0x12c3  yes     no
     as99127f rev.2 (type_name = as99127f)      0x31    0x5ca3  yes     no
     w83781d    7       3       0       3       0x10-1  0x5ca3  yes     yes
-    w83627hf   9       3       2       3       0x21    0x5ca3  yes     yes(LPC)
     w83782d    9       3       2-4     3       0x30    0x5ca3  yes     yes
     w83783s    5-6     3       2       1-2     0x40    0x5ca3  yes     no
 
 static struct platform_device *pdev;
 
 /* Addresses to scan */
-static unsigned short normal_i2c[] = { 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
-                                       0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
-                                       0x2c, 0x2d, 0x2e, 0x2f, I2C_CLIENT_END };
+static const unsigned short normal_i2c[] = { 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
+                                               0x2e, 0x2f, I2C_CLIENT_END };
 static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-I2C_CLIENT_INSMOD_5(w83781d, w83782d, w83783s, w83627hf, as99127f);
+I2C_CLIENT_INSMOD_4(w83781d, w83782d, w83783s, as99127f);
 I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
                    "{bus, clientaddr, subclientaddr1, subclientaddr2}");
 
@@ -114,7 +112,7 @@ MODULE_PARM_DESC(init, "Set to zero to bypass chip initialization");
 #define W83781D_REG_ALARM1             0x41
 #define W83781D_REG_ALARM2             0x42
 
-/* Real-time status (W83782D, W83783S, W83627HF) */
+/* Real-time status (W83782D, W83783S) */
 #define W83782D_REG_ALARM1             0x459
 #define W83782D_REG_ALARM2             0x45A
 #define W83782D_REG_ALARM3             0x45B
@@ -153,10 +151,6 @@ static const u8 BIT_SCFG2[] = { 0x10, 0x20, 0x40 };
 
 #define W83781D_DEFAULT_BETA           3435
 
-/* RT Table registers */
-#define W83781D_REG_RT_IDX             0x50
-#define W83781D_REG_RT_VAL             0x51
-
 /* Conversions */
 #define IN_TO_REG(val)                 SENSORS_LIMIT(((val) + 8) / 16, 0, 255)
 #define IN_FROM_REG(val)               ((val) * 16)
@@ -184,9 +178,9 @@ FAN_FROM_REG(u8 val, int div)
 #define TEMP_FROM_REG(val)             ((val) * 1000)
 
 #define BEEP_MASK_FROM_REG(val,type)   ((type) == as99127f ? \
-                                        (val) ^ 0x7fff : (val))
+                                        (~(val)) & 0x7fff : (val) & 0xff7fff)
 #define BEEP_MASK_TO_REG(val,type)     ((type) == as99127f ? \
-                                        (~(val)) & 0x7fff : (val) & 0xffffff)
+                                        (~(val)) & 0x7fff : (val) & 0xff7fff)
 
 #define DIV_FROM_REG(val)              (1 << (val))
 
@@ -246,7 +240,6 @@ struct w83781d_data {
        u8 vid;                 /* Register encoding, combined */
        u32 alarms;             /* Register encoding, combined */
        u32 beep_mask;          /* Register encoding, combined */
-       u8 beep_enable;         /* Boolean */
        u8 pwm[4];              /* Register value */
        u8 pwm2_enable;         /* Boolean */
        u16 sens[3];            /* 782D/783S only.
@@ -271,7 +264,6 @@ static struct i2c_driver w83781d_driver = {
        .driver = {
                .name = "w83781d",
        },
-       .id = I2C_DRIVERID_W83781D,
        .attach_adapter = w83781d_attach_adapter,
        .detach_client = w83781d_detach_client,
 };
@@ -520,11 +512,6 @@ static ssize_t show_beep_mask (struct device *dev, struct device_attribute *attr
        return sprintf(buf, "%ld\n",
                       (long)BEEP_MASK_FROM_REG(data->beep_mask, data->type));
 }
-static ssize_t show_beep_enable (struct device *dev, struct device_attribute *attr, char *buf)
-{
-       struct w83781d_data *data = w83781d_update_device(dev);
-       return sprintf(buf, "%ld\n", (long)data->beep_enable);
-}
 
 static ssize_t
 store_beep_mask(struct device *dev, struct device_attribute *attr,
@@ -536,12 +523,12 @@ store_beep_mask(struct device *dev, struct device_attribute *attr,
        val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
-       data->beep_mask = BEEP_MASK_TO_REG(val, data->type);
+       data->beep_mask &= 0x8000; /* preserve beep enable */
+       data->beep_mask |= BEEP_MASK_TO_REG(val, data->type);
        w83781d_write_value(data, W83781D_REG_BEEP_INTS1,
                            data->beep_mask & 0xff);
        w83781d_write_value(data, W83781D_REG_BEEP_INTS2,
-                           ((data->beep_mask >> 8) & 0x7f)
-                           | data->beep_enable << 7);
+                           (data->beep_mask >> 8) & 0xff);
        if (data->type != w83781d && data->type != as99127f) {
                w83781d_write_value(data, W83781D_REG_BEEP_INTS3,
                                    ((data->beep_mask) >> 16) & 0xff);
@@ -551,31 +538,8 @@ store_beep_mask(struct device *dev, struct device_attribute *attr,
        return count;
 }
 
-static ssize_t
-store_beep_enable(struct device *dev, struct device_attribute *attr,
-               const char *buf, size_t count)
-{
-       struct w83781d_data *data = dev_get_drvdata(dev);
-       u32 val;
-
-       val = simple_strtoul(buf, NULL, 10);
-       if (val != 0 && val != 1)
-               return -EINVAL;
-
-       mutex_lock(&data->update_lock);
-       data->beep_enable = val;
-       val = w83781d_read_value(data, W83781D_REG_BEEP_INTS2) & 0x7f;
-       val |= data->beep_enable << 7;
-       w83781d_write_value(data, W83781D_REG_BEEP_INTS2, val);
-       mutex_unlock(&data->update_lock);
-
-       return count;
-}
-
 static DEVICE_ATTR(beep_mask, S_IRUGO | S_IWUSR,
                show_beep_mask, store_beep_mask);
-static DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
-               show_beep_enable, store_beep_enable);
 
 static ssize_t show_beep(struct device *dev, struct device_attribute *attr,
                char *buf)
@@ -670,6 +634,8 @@ static SENSOR_DEVICE_ATTR(temp2_beep, S_IRUGO | S_IWUSR,
                        show_beep, store_beep, 5);
 static SENSOR_DEVICE_ATTR(temp3_beep, S_IRUGO,
                        show_temp3_beep, store_beep, 13);
+static SENSOR_DEVICE_ATTR(beep_enable, S_IRUGO | S_IWUSR,
+                       show_beep, store_beep, 15);
 
 static ssize_t
 show_fan_div(struct device *dev, struct device_attribute *da, char *buf)
@@ -696,7 +662,7 @@ store_fan_div(struct device *dev, struct device_attribute *da,
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
        mutex_lock(&data->update_lock);
-       
+
        /* Save fan_min */
        min = FAN_FROM_REG(data->fan_min[nr],
                           DIV_FROM_REG(data->fan_div[nr]));
@@ -963,8 +929,6 @@ w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
                client_name = "w83782d subclient";
        else if (kind == w83783s)
                client_name = "w83783s subclient";
-       else if (kind == w83627hf)
-               client_name = "w83627hf subclient";
        else if (kind == as99127f)
                client_name = "as99127f subclient";
 
@@ -1004,7 +968,7 @@ ERROR_SC_0:
 #define IN_UNIT_ATTRS(X)                                       \
        &sensor_dev_attr_in##X##_input.dev_attr.attr,           \
        &sensor_dev_attr_in##X##_min.dev_attr.attr,             \
-       &sensor_dev_attr_in##X##_max.dev_attr.attr,             \
+       &sensor_dev_attr_in##X##_max.dev_attr.attr,             \
        &sensor_dev_attr_in##X##_alarm.dev_attr.attr,           \
        &sensor_dev_attr_in##X##_beep.dev_attr.attr
 
@@ -1038,7 +1002,7 @@ static struct attribute* w83781d_attributes[] = {
        &dev_attr_vrm.attr,
        &dev_attr_alarms.attr,
        &dev_attr_beep_mask.attr,
-       &dev_attr_beep_enable.attr,
+       &sensor_dev_attr_beep_enable.dev_attr.attr,
        NULL
 };
 static const struct attribute_group w83781d_group = {
@@ -1268,9 +1232,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                        kind = w83782d;
                else if (val1 == 0x40 && vendid == winbond && address == 0x2d)
                        kind = w83783s;
-               else if (val1 == 0x21 && vendid == winbond)
-                       kind = w83627hf;
-               else if (val1 == 0x31 && address >= 0x28)
+               else if (val1 == 0x31)
                        kind = as99127f;
                else {
                        if (kind == 0)
@@ -1288,8 +1250,6 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
                client_name = "w83782d";
        } else if (kind == w83783s) {
                client_name = "w83783s";
-       } else if (kind == w83627hf) {
-               client_name = "w83627hf";
        } else if (kind == as99127f) {
                client_name = "as99127f";
        }
@@ -1380,7 +1340,8 @@ w83781d_isa_probe(struct platform_device *pdev)
 
        /* Reserve the ISA region */
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (!request_region(res->start, W83781D_EXTENT, "w83781d")) {
+       if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
+                           "w83781d")) {
                err = -EBUSY;
                goto exit;
        }
@@ -1396,10 +1357,6 @@ w83781d_isa_probe(struct platform_device *pdev)
 
        reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
        switch (reg) {
-       case 0x21:
-               data->type = w83627hf;
-               name = "w83627hf";
-               break;
        case 0x30:
                data->type = w83782d;
                name = "w83782d";
@@ -1432,7 +1389,7 @@ w83781d_isa_probe(struct platform_device *pdev)
        device_remove_file(&pdev->dev, &dev_attr_name);
        kfree(data);
  exit_release_region:
-       release_region(res->start, W83781D_EXTENT);
+       release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
  exit:
        return err;
 }
@@ -1446,16 +1403,16 @@ w83781d_isa_remove(struct platform_device *pdev)
        sysfs_remove_group(&pdev->dev.kobj, &w83781d_group);
        sysfs_remove_group(&pdev->dev.kobj, &w83781d_group_opt);
        device_remove_file(&pdev->dev, &dev_attr_name);
-       release_region(data->client.addr, W83781D_EXTENT);
+       release_region(data->client.addr + W83781D_ADDR_REG_OFFSET, 2);
        kfree(data);
 
        return 0;
 }
 
 /* The SMBus locks itself, usually, but nothing may access the Winbond between
-   bank switches. ISA access must always be locked explicitly! 
+   bank switches. ISA access must always be locked explicitly!
    We ignore the W83781D BUSY flag at this moment - it could lead to deadlocks,
-   would slow down the W83781D access and should not be necessary. 
+   would slow down the W83781D access and should not be necessary.
    There are some ugly typecasts here, but the good news is - they should
    nowhere else be necessary! */
 static int
@@ -1599,11 +1556,6 @@ w83781d_init_device(struct device *dev)
        int type = data->type;
        u8 tmp;
 
-       if (type == w83627hf)
-               dev_info(dev, "The W83627HF chip is better supported by the "
-                        "w83627hf driver, support will be dropped from the "
-                        "w83781d driver soon\n");
-
        if (reset && type != as99127f) { /* this resets registers we don't have
                                           documentation for on the as99127f */
                /* Resetting the chip has been the default for a long time,
@@ -1717,8 +1669,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                            w83781d_read_value(data, W83781D_REG_IN_MIN(i));
                        data->in_max[i] =
                            w83781d_read_value(data, W83781D_REG_IN_MAX(i));
-                       if ((data->type != w83782d)
-                           && (data->type != w83627hf) && (i == 6))
+                       if ((data->type != w83782d) && (i == 6))
                                break;
                }
                for (i = 0; i < 3; i++) {
@@ -1776,7 +1727,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                        data->fan_div[1] |= (i >> 4) & 0x04;
                        data->fan_div[2] |= (i >> 5) & 0x04;
                }
-               if ((data->type == w83782d) || (data->type == w83627hf)) {
+               if (data->type == w83782d) {
                        data->alarms = w83781d_read_value(data,
                                                W83782D_REG_ALARM1)
                                     | (w83781d_read_value(data,
@@ -1797,8 +1748,7 @@ static struct w83781d_data *w83781d_update_device(struct device *dev)
                                                W83781D_REG_ALARM2) << 8);
                }
                i = w83781d_read_value(data, W83781D_REG_BEEP_INTS2);
-               data->beep_enable = i >> 7;
-               data->beep_mask = ((i & 0x7f) << 8) +
+               data->beep_mask = (i << 8) +
                    w83781d_read_value(data, W83781D_REG_BEEP_INTS1);
                if ((data->type != w83781d) && (data->type != as99127f)) {
                        data->beep_mask |=
@@ -1820,8 +1770,17 @@ w83781d_isa_found(unsigned short address)
 {
        int val, save, found = 0;
 
-       if (!request_region(address, W83781D_EXTENT, "w83781d"))
+       /* We have to request the region in two parts because some
+          boards declare base+4 to base+7 as a PNP device */
+       if (!request_region(address, 4, "w83781d")) {
+               pr_debug("w83781d: Failed to request low part of region\n");
                return 0;
+       }
+       if (!request_region(address + 4, 4, "w83781d")) {
+               pr_debug("w83781d: Failed to request high part of region\n");
+               release_region(address, 4);
+               return 0;
+       }
 
 #define REALLY_SLOW_IO
        /* We need the timeouts for at least some W83781D-like
@@ -1886,17 +1845,16 @@ w83781d_isa_found(unsigned short address)
        outb_p(W83781D_REG_WCHIPID, address + W83781D_ADDR_REG_OFFSET);
        val = inb_p(address + W83781D_DATA_REG_OFFSET);
        if ((val & 0xfe) == 0x10        /* W83781D */
-        || val == 0x30                 /* W83782D */
-        || val == 0x21)                /* W83627HF */
+        || val == 0x30)                /* W83782D */
                found = 1;
 
        if (found)
                pr_info("w83781d: Found a %s chip at %#x\n",
-                       val == 0x21 ? "W83627HF" :
                        val == 0x30 ? "W83782D" : "W83781D", (int)address);
 
  release:
-       release_region(address, W83781D_EXTENT);
+       release_region(address + 4, 4);
+       release_region(address, 4);
        return found;
 }