Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into next
[pandora-kernel.git] / drivers / hwmon / smsc47m1.c
index d318196..d1b4985 100644 (file)
 #include <linux/sysfs.h>
 #include <asm/io.h>
 
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
 static struct platform_device *pdev;
 
 #define DRVNAME "smsc47m1"
@@ -116,7 +120,7 @@ struct smsc47m1_data {
        unsigned short addr;
        const char *name;
        enum chips type;
-       struct class_device *class_dev;
+       struct device *hwmon_dev;
 
        struct mutex update_lock;
        unsigned long last_updated;     /* In jiffies */
@@ -194,6 +198,14 @@ static ssize_t get_fan_div(struct device *dev, struct device_attribute
        return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[attr->index]));
 }
 
+static ssize_t get_fan_alarm(struct device *dev, struct device_attribute
+                            *devattr, char *buf)
+{
+       int bitnr = to_sensor_dev_attr(devattr)->index;
+       struct smsc47m1_data *data = smsc47m1_update_device(dev, 0);
+       return sprintf(buf, "%u\n", (data->alarms >> bitnr) & 1);
+}
+
 static ssize_t get_pwm(struct device *dev, struct device_attribute
                       *devattr, char *buf)
 {
@@ -343,6 +355,8 @@ static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,             \
                get_fan_min, set_fan_min, offset - 1);                  \
 static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,                \
                get_fan_div, set_fan_div, offset - 1);                  \
+static SENSOR_DEVICE_ATTR(fan##offset##_alarm, S_IRUGO, get_fan_alarm, \
+               NULL, offset - 1);                                      \
 static SENSOR_DEVICE_ATTR(pwm##offset, S_IRUGO | S_IWUSR,              \
                get_pwm, set_pwm, offset - 1);                          \
 static SENSOR_DEVICE_ATTR(pwm##offset##_enable, S_IRUGO | S_IWUSR,     \
@@ -370,12 +384,15 @@ static struct attribute *smsc47m1_attributes[] = {
        &sensor_dev_attr_fan1_input.dev_attr.attr,
        &sensor_dev_attr_fan1_min.dev_attr.attr,
        &sensor_dev_attr_fan1_div.dev_attr.attr,
+       &sensor_dev_attr_fan1_alarm.dev_attr.attr,
        &sensor_dev_attr_fan2_input.dev_attr.attr,
        &sensor_dev_attr_fan2_min.dev_attr.attr,
        &sensor_dev_attr_fan2_div.dev_attr.attr,
+       &sensor_dev_attr_fan2_alarm.dev_attr.attr,
        &sensor_dev_attr_fan3_input.dev_attr.attr,
        &sensor_dev_attr_fan3_min.dev_attr.attr,
        &sensor_dev_attr_fan3_div.dev_attr.attr,
+       &sensor_dev_attr_fan3_alarm.dev_attr.attr,
 
        &sensor_dev_attr_pwm1.dev_attr.attr,
        &sensor_dev_attr_pwm1_enable.dev_attr.attr,
@@ -399,7 +416,7 @@ static int __init smsc47m1_find(unsigned short *addr,
        u8 val;
 
        superio_enter();
-       val = superio_inb(SUPERIO_REG_DEVID);
+       val = force_id ? force_id : superio_inb(SUPERIO_REG_DEVID);
 
        /*
         * SMSC LPC47M10x/LPC47M112/LPC47M13x (device id 0x59), LPC47M14x
@@ -529,7 +546,9 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
                 || (err = device_create_file(dev,
                                &sensor_dev_attr_fan1_min.dev_attr))
                 || (err = device_create_file(dev,
-                               &sensor_dev_attr_fan1_div.dev_attr)))
+                               &sensor_dev_attr_fan1_div.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan1_alarm.dev_attr)))
                        goto error_remove_files;
        } else
                dev_dbg(dev, "Fan 1 not enabled by hardware, skipping\n");
@@ -540,7 +559,9 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
                 || (err = device_create_file(dev,
                                &sensor_dev_attr_fan2_min.dev_attr))
                 || (err = device_create_file(dev,
-                               &sensor_dev_attr_fan2_div.dev_attr)))
+                               &sensor_dev_attr_fan2_div.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan2_alarm.dev_attr)))
                        goto error_remove_files;
        } else
                dev_dbg(dev, "Fan 2 not enabled by hardware, skipping\n");
@@ -551,9 +572,11 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
                 || (err = device_create_file(dev,
                                &sensor_dev_attr_fan3_min.dev_attr))
                 || (err = device_create_file(dev,
-                               &sensor_dev_attr_fan3_div.dev_attr)))
+                               &sensor_dev_attr_fan3_div.dev_attr))
+                || (err = device_create_file(dev,
+                               &sensor_dev_attr_fan3_alarm.dev_attr)))
                        goto error_remove_files;
-       } else
+       } else if (data->type == smsc47m2)
                dev_dbg(dev, "Fan 3 not enabled by hardware, skipping\n");
 
        if (pwm1) {
@@ -580,7 +603,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
                 || (err = device_create_file(dev,
                                &sensor_dev_attr_pwm3_enable.dev_attr)))
                        goto error_remove_files;
-       } else
+       } else if (data->type == smsc47m2)
                dev_dbg(dev, "PWM 3 not enabled by hardware, skipping\n");
 
        if ((err = device_create_file(dev, &dev_attr_alarms)))
@@ -588,9 +611,9 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
        if ((err = device_create_file(dev, &dev_attr_name)))
                goto error_remove_files;
 
-       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 error_remove_files;
        }
 
@@ -611,7 +634,7 @@ static int __devexit smsc47m1_remove(struct platform_device *pdev)
        struct smsc47m1_data *data = platform_get_drvdata(pdev);
        struct resource *res;
 
-       hwmon_device_unregister(data->class_dev);
+       hwmon_device_unregister(data->hwmon_dev);
        sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);