]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/hwmon/lm78.c
[PATCH] savagefb: Convert from VGA IO access to MMIO access
[linux-2.6-omap-h63xx.git] / drivers / hwmon / lm78.c
index 29241469dcbac09d2617c365e7b5388fc6908308..bde0cda9477e1a52c62e3960dd1022185c5e838a 100644 (file)
 #include <linux/slab.h>
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
-#include <linux/i2c-sensor.h>
+#include <linux/i2c-isa.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
 #include <asm/io.h>
 
 /* Addresses to scan */
@@ -31,10 +34,10 @@ 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 unsigned int normal_isa[] = { 0x0290, I2C_CLIENT_ISA_END };
+static unsigned short isa_address = 0x290;
 
 /* Insmod parameters */
-SENSORS_INSMOD_3(lm78, lm78j, lm79);
+I2C_CLIENT_INSMOD_2(lm78, lm79);
 
 /* Many LM78 constants specified below */
 
@@ -104,13 +107,6 @@ static inline int TEMP_FROM_REG(s8 val)
        return val * 1000;
 }
 
-/* VID: mV
-   REG: (see doc/vid) */
-static inline int VID_FROM_REG(u8 val)
-{
-       return val==0x1f ? 0 : val>=0x10 ? 5100-val*100 : 2050-val*50;
-}
-
 #define DIV_FROM_REG(val) (1 << (val))
 
 /* There are some complications in a module like this. First off, LM78 chips
@@ -134,6 +130,7 @@ static inline int VID_FROM_REG(u8 val)
    allocated. */
 struct lm78_data {
        struct i2c_client client;
+       struct class_device *class_dev;
        struct semaphore lock;
        enum chips type;
 
@@ -156,6 +153,7 @@ struct lm78_data {
 
 
 static int lm78_attach_adapter(struct i2c_adapter *adapter);
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter);
 static int lm78_detect(struct i2c_adapter *adapter, int address, int kind);
 static int lm78_detach_client(struct i2c_client *client);
 
@@ -174,6 +172,14 @@ static struct i2c_driver lm78_driver = {
        .detach_client  = lm78_detach_client,
 };
 
+static struct i2c_driver lm78_isa_driver = {
+       .owner          = THIS_MODULE,
+       .name           = "lm78-isa",
+       .attach_adapter = lm78_isa_attach_adapter,
+       .detach_client  = lm78_detach_client,
+};
+
+
 /* 7 Voltages */
 static ssize_t show_in(struct device *dev, char *buf, int nr)
 {
@@ -445,7 +451,7 @@ static DEVICE_ATTR(fan3_div, S_IRUGO, show_fan_3_div, NULL);
 static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
 {
        struct lm78_data *data = lm78_update_device(dev);
-       return sprintf(buf, "%d\n", VID_FROM_REG(data->vid));
+       return sprintf(buf, "%d\n", vid_from_reg(82, data->vid));
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
 
@@ -465,11 +471,16 @@ static int lm78_attach_adapter(struct i2c_adapter *adapter)
 {
        if (!(adapter->class & I2C_CLASS_HWMON))
                return 0;
-       return i2c_detect(adapter, &addr_data, lm78_detect);
+       return i2c_probe(adapter, &addr_data, lm78_detect);
+}
+
+static int lm78_isa_attach_adapter(struct i2c_adapter *adapter)
+{
+       return lm78_detect(adapter, isa_address, -1);
 }
 
-/* This function is called by i2c_detect */
-int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
+/* This function is called by i2c_probe */
+static int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 {
        int i, err;
        struct i2c_client *new_client;
@@ -485,7 +496,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Reserve the ISA region */
        if (is_isa)
-               if (!request_region(address, LM78_EXTENT, lm78_driver.name)) {
+               if (!request_region(address, LM78_EXTENT,
+                                   lm78_isa_driver.name)) {
                        err = -EBUSY;
                        goto ERROR0;
                }
@@ -528,11 +540,10 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
           client structure, even though we cannot fill it completely yet.
           But it allows us to access lm78_{read,write}_value. */
 
-       if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
+       if (!(data = kzalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
                err = -ENOMEM;
                goto ERROR1;
        }
-       memset(data, 0, sizeof(struct lm78_data));
 
        new_client = &data->client;
        if (is_isa)
@@ -540,7 +551,7 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        i2c_set_clientdata(new_client, data);
        new_client->addr = address;
        new_client->adapter = adapter;
-       new_client->driver = &lm78_driver;
+       new_client->driver = is_isa ? &lm78_isa_driver : &lm78_driver;
        new_client->flags = 0;
 
        /* Now, we do the remaining detection. */
@@ -559,10 +570,9 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        /* Determine the chip type. */
        if (kind <= 0) {
                i = lm78_read_value(new_client, LM78_REG_CHIPID);
-               if (i == 0x00 || i == 0x20)
+               if (i == 0x00 || i == 0x20      /* LM78 */
+                || i == 0x40)                  /* LM78-J */
                        kind = lm78;
-               else if (i == 0x40)
-                       kind = lm78j;
                else if ((i & 0xfe) == 0xc0)
                        kind = lm79;
                else {
@@ -578,8 +588,6 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        if (kind == lm78) {
                client_name = "lm78";
-       } else if (kind == lm78j) {
-               client_name = "lm78-j";
        } else if (kind == lm79) {
                client_name = "lm79";
        }
@@ -605,6 +613,12 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
        }
 
        /* Register sysfs hooks */
+       data->class_dev = hwmon_device_register(&new_client->dev);
+       if (IS_ERR(data->class_dev)) {
+               err = PTR_ERR(data->class_dev);
+               goto ERROR3;
+       }
+
        device_create_file(&new_client->dev, &dev_attr_in0_input);
        device_create_file(&new_client->dev, &dev_attr_in0_min);
        device_create_file(&new_client->dev, &dev_attr_in0_max);
@@ -643,6 +657,8 @@ int lm78_detect(struct i2c_adapter *adapter, int address, int kind)
 
        return 0;
 
+ERROR3:
+       i2c_detach_client(new_client);
 ERROR2:
        kfree(data);
 ERROR1:
@@ -654,18 +670,18 @@ ERROR0:
 
 static int lm78_detach_client(struct i2c_client *client)
 {
+       struct lm78_data *data = i2c_get_clientdata(client);
        int err;
 
-       if ((err = i2c_detach_client(client))) {
-               dev_err(&client->dev,
-                   "Client deregistration failed, client not detached.\n");
+       hwmon_device_unregister(data->class_dev);
+
+       if ((err = i2c_detach_client(client)))
                return err;
-       }
 
        if(i2c_is_isa_client(client))
                release_region(client->addr, LM78_EXTENT);
 
-       kfree(i2c_get_clientdata(client));
+       kfree(data);
 
        return 0;
 }
@@ -709,7 +725,6 @@ static int lm78_write_value(struct i2c_client *client, u8 reg, u8 value)
                return i2c_smbus_write_byte_data(client, reg, value);
 }
 
-/* Called when we have found a new LM78. It should set limits, etc. */
 static void lm78_init_client(struct i2c_client *client)
 {
        u8 config = lm78_read_value(client, LM78_REG_CONFIG);
@@ -777,18 +792,31 @@ static struct lm78_data *lm78_update_device(struct device *dev)
 
 static int __init sm_lm78_init(void)
 {
-       return i2c_add_driver(&lm78_driver);
+       int res;
+
+       res = i2c_add_driver(&lm78_driver);
+       if (res)
+               return res;
+
+       res = i2c_isa_add_driver(&lm78_isa_driver);
+       if (res) {
+               i2c_del_driver(&lm78_driver);
+               return res;
+       }
+
+       return 0;
 }
 
 static void __exit sm_lm78_exit(void)
 {
+       i2c_isa_del_driver(&lm78_isa_driver);
        i2c_del_driver(&lm78_driver);
 }
 
 
 
 MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>");
-MODULE_DESCRIPTION("LM78, LM78-J and LM79 driver");
+MODULE_DESCRIPTION("LM78/LM79 driver");
 MODULE_LICENSE("GPL");
 
 module_init(sm_lm78_init);