[BNX2]: PHY workaround for 5709 A0.
[powerpc.git] / drivers / hwmon / via686a.c
index eb84997..f8acada 100644 (file)
 #include <linux/hwmon.h>
 #include <linux/err.h>
 #include <linux/init.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
 #include <asm/io.h>
 
 
 /* If force_addr is set to anything different from 0, we forcibly enable
    the device at the given address. */
-static unsigned short force_addr = 0;
+static unsigned short force_addr;
 module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
                 "Initialize the base address of the sensors");
@@ -198,7 +200,7 @@ static inline u8 FAN_TO_REG(long rpm, int div)
  but the function is very linear in the useful range (0-80 deg C), so
  we'll just use linear interpolation for 10-bit readings.)  So, tempLUT
  is the temp at via register values 0-255: */
-static const long tempLUT[] =
+static const s16 tempLUT[] =
 { -709, -688, -667, -646, -627, -607, -589, -570, -553, -536, -519,
        -503, -487, -471, -456, -442, -428, -414, -400, -387, -375,
        -362, -350, -339, -327, -316, -305, -295, -285, -275, -265,
@@ -270,7 +272,7 @@ static inline u8 TEMP_TO_REG(long val)
 }
 
 /* for 8-bit temperature hyst and over registers */
-#define TEMP_FROM_REG(val) (tempLUT[(val)] * 100)
+#define TEMP_FROM_REG(val)     ((long)tempLUT[val] * 100)
 
 /* for 10-bit temperature readings */
 static inline long TEMP_FROM_REG10(u16 val)
@@ -296,7 +298,7 @@ static inline long TEMP_FROM_REG10(u16 val)
 struct via686a_data {
        struct i2c_client client;
        struct class_device *class_dev;
-       struct semaphore update_lock;
+       struct mutex update_lock;
        char valid;             /* !=0 if following fields are valid */
        unsigned long last_updated;     /* In jiffies */
 
@@ -355,11 +357,11 @@ static ssize_t set_in_min(struct device *dev, const char *buf,
        struct via686a_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        data->in_min[nr] = IN_TO_REG(val, nr);
        via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
                        data->in_min[nr]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 static ssize_t set_in_max(struct device *dev, const char *buf,
@@ -368,11 +370,11 @@ static ssize_t set_in_max(struct device *dev, const char *buf,
        struct via686a_data *data = i2c_get_clientdata(client);
        unsigned long val = simple_strtoul(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        data->in_max[nr] = IN_TO_REG(val, nr);
        via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
                        data->in_max[nr]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 #define show_in_offset(offset)                                 \
@@ -432,11 +434,11 @@ static ssize_t set_temp_over(struct device *dev, const char *buf,
        struct via686a_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        data->temp_over[nr] = TEMP_TO_REG(val);
        via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr],
                            data->temp_over[nr]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 static ssize_t set_temp_hyst(struct device *dev, const char *buf,
@@ -445,11 +447,11 @@ static ssize_t set_temp_hyst(struct device *dev, const char *buf,
        struct via686a_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        data->temp_hyst[nr] = TEMP_TO_REG(val);
        via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr],
                            data->temp_hyst[nr]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 #define show_temp_offset(offset)                                       \
@@ -508,10 +510,10 @@ static ssize_t set_fan_min(struct device *dev, const char *buf,
        struct via686a_data *data = i2c_get_clientdata(client);
        int val = simple_strtol(buf, NULL, 10);
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
        via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 static ssize_t set_fan_div(struct device *dev, const char *buf,
@@ -521,12 +523,12 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
        int val = simple_strtol(buf, NULL, 10);
        int old;
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
        old = via686a_read_value(client, VIA686A_REG_FANDIV);
        data->fan_div[nr] = DIV_TO_REG(val);
        old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
        via686a_write_value(client, VIA686A_REG_FANDIV, old);
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
        return count;
 }
 
@@ -569,11 +571,55 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static struct attribute *via686a_attributes[] = {
+       &dev_attr_in0_input.attr,
+       &dev_attr_in1_input.attr,
+       &dev_attr_in2_input.attr,
+       &dev_attr_in3_input.attr,
+       &dev_attr_in4_input.attr,
+       &dev_attr_in0_min.attr,
+       &dev_attr_in1_min.attr,
+       &dev_attr_in2_min.attr,
+       &dev_attr_in3_min.attr,
+       &dev_attr_in4_min.attr,
+       &dev_attr_in0_max.attr,
+       &dev_attr_in1_max.attr,
+       &dev_attr_in2_max.attr,
+       &dev_attr_in3_max.attr,
+       &dev_attr_in4_max.attr,
+
+       &dev_attr_temp1_input.attr,
+       &dev_attr_temp2_input.attr,
+       &dev_attr_temp3_input.attr,
+       &dev_attr_temp1_max.attr,
+       &dev_attr_temp2_max.attr,
+       &dev_attr_temp3_max.attr,
+       &dev_attr_temp1_max_hyst.attr,
+       &dev_attr_temp2_max_hyst.attr,
+       &dev_attr_temp3_max_hyst.attr,
+
+       &dev_attr_fan1_input.attr,
+       &dev_attr_fan2_input.attr,
+       &dev_attr_fan1_min.attr,
+       &dev_attr_fan2_min.attr,
+       &dev_attr_fan1_div.attr,
+       &dev_attr_fan2_div.attr,
+
+       &dev_attr_alarms.attr,
+       NULL
+};
+
+static const struct attribute_group via686a_group = {
+       .attrs = via686a_attributes,
+};
+
 /* The driver. I choose to use type i2c_driver, as at is identical to both
    smbus_driver and isa_driver, and clients could be of either kind */
 static struct i2c_driver via686a_driver = {
-       .owner          = THIS_MODULE,
-       .name           = "via686a",
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name   = "via686a",
+       },
        .attach_adapter = via686a_detect,
        .detach_client  = via686a_detach_client,
 };
@@ -589,10 +635,8 @@ static int via686a_detect(struct i2c_adapter *adapter)
        u16 val;
 
        /* 8231 requires multiple of 256, we enforce that on 686 as well */
-       if (force_addr)
-               address = force_addr & 0xFF00;
-
        if (force_addr) {
+               address = force_addr & 0xFF00;
                dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
                         address);
                if (PCIBIOS_SUCCESSFUL !=
@@ -603,25 +647,31 @@ static int via686a_detect(struct i2c_adapter *adapter)
            pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
                return -ENODEV;
        if (!(val & 0x0001)) {
-               dev_warn(&adapter->dev, "enabling sensors\n");
-               if (PCIBIOS_SUCCESSFUL !=
-                   pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
-                                         val | 0x0001))
+               if (force_addr) {
+                       dev_info(&adapter->dev, "enabling sensors\n");
+                       if (PCIBIOS_SUCCESSFUL !=
+                           pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
+                                                 val | 0x0001))
+                               return -ENODEV;
+               } else {
+                       dev_warn(&adapter->dev, "sensors disabled - enable "
+                                "with force_addr=0x%x\n", address);
                        return -ENODEV;
+               }
        }
 
        /* Reserve the ISA region */
-       if (!request_region(address, VIA686A_EXTENT, via686a_driver.name)) {
+       if (!request_region(address, VIA686A_EXTENT,
+                           via686a_driver.driver.name)) {
                dev_err(&adapter->dev, "region 0x%x already in use!\n",
                        address);
                return -ENODEV;
        }
 
-       if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
+       if (!(data = kzalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
                err = -ENOMEM;
                goto exit_release;
        }
-       memset(data, 0, sizeof(struct via686a_data));
 
        new_client = &data->client;
        i2c_set_clientdata(new_client, data);
@@ -634,7 +684,7 @@ static int via686a_detect(struct i2c_adapter *adapter)
        strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
 
        data->valid = 0;
-       init_MUTEX(&data->update_lock);
+       mutex_init(&data->update_lock);
        /* Tell the I2C layer a new client has arrived */
        if ((err = i2c_attach_client(new_client)))
                goto exit_free;
@@ -643,46 +693,19 @@ static int via686a_detect(struct i2c_adapter *adapter)
        via686a_init_client(new_client);
 
        /* Register sysfs hooks */
+       if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group)))
+               goto exit_detach;
+
        data->class_dev = hwmon_device_register(&new_client->dev);
        if (IS_ERR(data->class_dev)) {
                err = PTR_ERR(data->class_dev);
-               goto exit_detach;
+               goto exit_remove_files;
        }
 
-       device_create_file(&new_client->dev, &dev_attr_in0_input);
-       device_create_file(&new_client->dev, &dev_attr_in1_input);
-       device_create_file(&new_client->dev, &dev_attr_in2_input);
-       device_create_file(&new_client->dev, &dev_attr_in3_input);
-       device_create_file(&new_client->dev, &dev_attr_in4_input);
-       device_create_file(&new_client->dev, &dev_attr_in0_min);
-       device_create_file(&new_client->dev, &dev_attr_in1_min);
-       device_create_file(&new_client->dev, &dev_attr_in2_min);
-       device_create_file(&new_client->dev, &dev_attr_in3_min);
-       device_create_file(&new_client->dev, &dev_attr_in4_min);
-       device_create_file(&new_client->dev, &dev_attr_in0_max);
-       device_create_file(&new_client->dev, &dev_attr_in1_max);
-       device_create_file(&new_client->dev, &dev_attr_in2_max);
-       device_create_file(&new_client->dev, &dev_attr_in3_max);
-       device_create_file(&new_client->dev, &dev_attr_in4_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_input);
-       device_create_file(&new_client->dev, &dev_attr_temp2_input);
-       device_create_file(&new_client->dev, &dev_attr_temp3_input);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max);
-       device_create_file(&new_client->dev, &dev_attr_temp3_max);
-       device_create_file(&new_client->dev, &dev_attr_temp1_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp2_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_temp3_max_hyst);
-       device_create_file(&new_client->dev, &dev_attr_fan1_input);
-       device_create_file(&new_client->dev, &dev_attr_fan2_input);
-       device_create_file(&new_client->dev, &dev_attr_fan1_min);
-       device_create_file(&new_client->dev, &dev_attr_fan2_min);
-       device_create_file(&new_client->dev, &dev_attr_fan1_div);
-       device_create_file(&new_client->dev, &dev_attr_fan2_div);
-       device_create_file(&new_client->dev, &dev_attr_alarms);
-
        return 0;
 
+exit_remove_files:
+       sysfs_remove_group(&new_client->dev.kobj, &via686a_group);
 exit_detach:
        i2c_detach_client(new_client);
 exit_free:
@@ -698,6 +721,7 @@ static int via686a_detach_client(struct i2c_client *client)
        int err;
 
        hwmon_device_unregister(data->class_dev);
+       sysfs_remove_group(&client->dev.kobj, &via686a_group);
 
        if ((err = i2c_detach_client(client)))
                return err;
@@ -708,7 +732,6 @@ static int via686a_detach_client(struct i2c_client *client)
        return 0;
 }
 
-/* Called when we have found a new VIA686A. Set limits, etc. */
 static void via686a_init_client(struct i2c_client *client)
 {
        u8 reg;
@@ -729,7 +752,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
        struct via686a_data *data = i2c_get_clientdata(client);
        int i;
 
-       down(&data->update_lock);
+       mutex_lock(&data->update_lock);
 
        if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
            || !data->valid) {
@@ -784,7 +807,7 @@ static struct via686a_data *via686a_update_device(struct device *dev)
                data->valid = 1;
        }
 
-       up(&data->update_lock);
+       mutex_unlock(&data->update_lock);
 
        return data;
 }
@@ -812,11 +835,6 @@ static int __devinit via686a_pci_probe(struct pci_dev *dev,
                return -ENODEV;
        }
 
-       if (!address) {
-               dev_err(&dev->dev, "No Via 686A sensors found.\n");
-               return -ENODEV;
-       }
-
        s_bridge = pci_dev_get(dev);
        if (i2c_isa_add_driver(&via686a_driver)) {
                pci_dev_put(s_bridge);