From: Jean Delvare <khali@linux-fr.org>
To: lm-sensors@vger.kernel.org
Subject: Re: [lm-sensors] [PATCH 1/2] hwmon: w83781d: make ISA interface
Date: Mon, 06 Oct 2008 13:13:52 +0000 [thread overview]
Message-ID: <20081006151352.7e73c909@hyperion.delvare> (raw)
In-Reply-To: <48CB7F6D.8010109@grandegger.com>
Hi Wolfgang,
On Sat, 13 Sep 2008 10:53:01 +0200, Wolfgang Grandegger wrote:
> Probing the ISA bus on systems without ISA bus may hang the system.
> This patch makes the ISA bus related code depend on the kernel
> configuration parameter CONFIG_ISA. It moves ISA bus related code
> into one #ifdef CONFIG_ISA ... #endif block and adds some helper
> function.
As said before, this patch is a little bigger than I hoped for, but I
admit it nicely optimizes the size of the driver when CONFIG_ISA isn't
set. So, so be it, I'm taking it.
>
> Note that this patch is based on the patches:
>
> hwmon-w83781d-01-refactor-beep-enable.patch
> hwmon-w83781d-02-alias-detect.patch
>
> from http://jdelvare.pck.nerim.net/sensors/w83781d/.
>
> Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
> ---
> drivers/hwmon/w83781d.c | 666 +++++++++++++++++++++++++++---------------------
> 1 file changed, 388 insertions(+), 278 deletions(-)
>
> Index: linux-2.6-denx/drivers/hwmon/w83781d.c
> =================================> --- linux-2.6-denx.orig/drivers/hwmon/w83781d.c
> +++ linux-2.6-denx/drivers/hwmon/w83781d.c
> @@ -49,14 +49,9 @@
> #include <asm/io.h>
> #include "lm75.h"
You can put the inclusion of <linux/platform_device.h>,
<linux/ioport.h> and <asm/io.h> inside #ifdef CONFIG_ISA as well. This
will avoid unneeded rebuilds.
>
> -/* ISA device, if found */
> -static struct platform_device *pdev;
> -
> /* Addresses to scan */
> 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_4(w83781d, w83782d, w83783s, as99127f);
> I2C_CLIENT_MODULE_PARM(force_subclients, "List of subclient addresses: "
> @@ -245,13 +240,13 @@ struct w83781d_data {
> u8 vrm;
> };
>
> +static struct w83781d_data *w83781d_data_if_isa(void);
> +static int w83781d_alias_detect(struct i2c_client *client, u8 chipid);
> +
> static int w83781d_attach_adapter(struct i2c_adapter *adapter);
> static int w83781d_detect(struct i2c_adapter *adapter, int address, int kind);
> static int w83781d_detach_client(struct i2c_client *client);
>
> -static int __devinit w83781d_isa_probe(struct platform_device *pdev);
> -static int __devexit w83781d_isa_remove(struct platform_device *pdev);
> -
> static int w83781d_read_value(struct w83781d_data *data, u16 reg);
> static int w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value);
> static struct w83781d_data *w83781d_update_device(struct device *dev);
> @@ -265,16 +260,6 @@ static struct i2c_driver w83781d_driver
> .detach_client = w83781d_detach_client,
> };
>
> -static struct platform_driver w83781d_isa_driver = {
> - .driver = {
> - .owner = THIS_MODULE,
> - .name = "w83781d",
> - },
> - .probe = w83781d_isa_probe,
> - .remove = w83781d_isa_remove,
> -};
> -
> -
> /* following are the sysfs callback functions */
> #define show_in_reg(reg) \
> static ssize_t show_##reg (struct device *dev, struct device_attribute *da, \
> @@ -836,16 +821,6 @@ static SENSOR_DEVICE_ATTR(temp2_type, S_
> static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
> show_sensor, store_sensor, 2);
>
> -/* I2C devices get this name attribute automatically, but for ISA devices
> - we must create it by ourselves. */
> -static ssize_t
> -show_name(struct device *dev, struct device_attribute *devattr, char *buf)
> -{
> - struct w83781d_data *data = dev_get_drvdata(dev);
> - return sprintf(buf, "%s\n", data->client.name);
> -}
> -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
> -
> /* This function is called when:
> * w83781d_driver is inserted (when this module is loaded), for each
> available adapter
> @@ -855,13 +830,12 @@ static DEVICE_ATTR(name, S_IRUGO, show_n
> static int
> w83781d_attach_adapter(struct i2c_adapter *adapter)
> {
> - struct w83781d_data *data;
> + struct w83781d_data *data = w83781d_data_if_isa();
> int err;
>
> if (!(adapter->class & I2C_CLASS_HWMON))
> return 0;
>
> - data = pdev ? platform_get_drvdata(pdev) : NULL;
> if (data)
> mutex_lock(&data->update_lock);
> err = i2c_probe(adapter, &addr_data, w83781d_detect);
> @@ -1037,40 +1011,6 @@ static const struct attribute_group w837
> .attrs = w83781d_attributes_opt,
> };
>
> -/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
> -static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
> -{
> - struct w83781d_data *i2c, *isa;
> - int i;
> -
> - if (!pdev) /* No ISA chip */
> - return 0;
> -
> - i2c = i2c_get_clientdata(client);
> - isa = platform_get_drvdata(pdev);
> -
> - if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
> - return 0; /* Address doesn't match */
> - if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
> - return 0; /* Chip type doesn't match */
> -
> - /* We compare all the limit registers, the config register and the
> - * interrupt mask registers */
> - for (i = 0x2b; i <= 0x3d; i++) {
> - if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
> - return 0;
> - }
> - if (w83781d_read_value(isa, W83781D_REG_CONFIG) !> - w83781d_read_value(i2c, W83781D_REG_CONFIG))
> - return 0;
> - for (i = 0x43; i <= 0x46; i++) {
> - if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
> - return 0;
> - }
> -
> - return 1;
> -}
> -
> /* No clean up is done on error, it's up to the caller */
> static int
> w83781d_create_files(struct device *dev, int kind, int is_isa)
> @@ -1167,12 +1107,6 @@ w83781d_create_files(struct device *dev,
> }
> }
>
> - if (is_isa) {
> - err = device_create_file(&pdev->dev, &dev_attr_name);
> - if (err)
> - return err;
> - }
> -
> return 0;
> }
>
> @@ -1381,221 +1315,80 @@ w83781d_detach_client(struct i2c_client
> return 0;
> }
>
> -static int __devinit
> -w83781d_isa_probe(struct platform_device *pdev)
> -{
> - int err, reg;
> - struct w83781d_data *data;
> - struct resource *res;
> - const char *name;
> -
> - /* Reserve the ISA region */
> - res = platform_get_resource(pdev, IORESOURCE_IO, 0);
> - if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
> - "w83781d")) {
> - err = -EBUSY;
> - goto exit;
> - }
> -
> - if (!(data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
> - err = -ENOMEM;
> - goto exit_release_region;
> - }
> - mutex_init(&data->lock);
> - data->client.addr = res->start;
> - i2c_set_clientdata(&data->client, data);
> - platform_set_drvdata(pdev, data);
> -
> - reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
> - switch (reg) {
> - case 0x30:
> - data->type = w83782d;
> - name = "w83782d";
> - break;
> - default:
> - data->type = w83781d;
> - name = "w83781d";
> - }
> - strlcpy(data->client.name, name, I2C_NAME_SIZE);
> -
> - /* Initialize the W83781D chip */
> - w83781d_init_device(&pdev->dev);
> -
> - /* Register sysfs hooks */
> - err = w83781d_create_files(&pdev->dev, data->type, 1);
> - if (err)
> - goto exit_remove_files;
> -
> - data->hwmon_dev = hwmon_device_register(&pdev->dev);
> - if (IS_ERR(data->hwmon_dev)) {
> - err = PTR_ERR(data->hwmon_dev);
> - goto exit_remove_files;
> - }
> -
> - return 0;
> -
> - exit_remove_files:
> - 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);
> - kfree(data);
> - exit_release_region:
> - release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
> - exit:
> - return err;
> -}
> -
> -static int __devexit
> -w83781d_isa_remove(struct platform_device *pdev)
> -{
> - struct w83781d_data *data = platform_get_drvdata(pdev);
> -
> - hwmon_device_unregister(data->hwmon_dev);
> - 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_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!
> - 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.
> - There are some ugly typecasts here, but the good news is - they should
> - nowhere else be necessary! */
> static int
> -w83781d_read_value(struct w83781d_data *data, u16 reg)
> +w83781d_read_value_i2c(struct w83781d_data *data, u16 reg)
> {
> struct i2c_client *client = &data->client;
> - int res, word_sized, bank;
> + int res, bank;
> struct i2c_client *cl;
>
> - mutex_lock(&data->lock);
> - if (!client->driver) { /* ISA device */
> - word_sized = (((reg & 0xff00) = 0x100)
> - || ((reg & 0xff00) = 0x200))
> - && (((reg & 0x00ff) = 0x50)
> - || ((reg & 0x00ff) = 0x53)
> - || ((reg & 0x00ff) = 0x55));
> - if (reg & 0xff00) {
> - outb_p(W83781D_REG_BANK,
> - client->addr + W83781D_ADDR_REG_OFFSET);
> - outb_p(reg >> 8,
> - client->addr + W83781D_DATA_REG_OFFSET);
> - }
> - outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
> - res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
> - if (word_sized) {
> - outb_p((reg & 0xff) + 1,
> - client->addr + W83781D_ADDR_REG_OFFSET);
> - res > - (res << 8) + inb_p(client->addr +
> - W83781D_DATA_REG_OFFSET);
> - }
> - if (reg & 0xff00) {
> - outb_p(W83781D_REG_BANK,
> - client->addr + W83781D_ADDR_REG_OFFSET);
> - outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
> - }
> + bank = (reg >> 8) & 0x0f;
> + if (bank > 2)
> + /* switch banks */
> + i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
> + bank);
> + if (bank = 0 || bank > 2) {
> + res = i2c_smbus_read_byte_data(client, reg & 0xff);
> } else {
> - bank = (reg >> 8) & 0x0f;
> - if (bank > 2)
> - /* switch banks */
> - i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
> - bank);
> - if (bank = 0 || bank > 2) {
> - res = i2c_smbus_read_byte_data(client, reg & 0xff);
> - } else {
> - /* switch to subclient */
> - cl = data->lm75[bank - 1];
> - /* convert from ISA to LM75 I2C addresses */
> - switch (reg & 0xff) {
> - case 0x50: /* TEMP */
> - res = swab16(i2c_smbus_read_word_data(cl, 0));
> - break;
> - case 0x52: /* CONFIG */
> - res = i2c_smbus_read_byte_data(cl, 1);
> - break;
> - case 0x53: /* HYST */
> - res = swab16(i2c_smbus_read_word_data(cl, 2));
> - break;
> - case 0x55: /* OVER */
> - default:
> - res = swab16(i2c_smbus_read_word_data(cl, 3));
> - break;
> - }
> + /* switch to subclient */
> + cl = data->lm75[bank - 1];
> + /* convert from ISA to LM75 I2C addresses */
> + switch (reg & 0xff) {
> + case 0x50: /* TEMP */
> + res = swab16(i2c_smbus_read_word_data(cl, 0));
> + break;
> + case 0x52: /* CONFIG */
> + res = i2c_smbus_read_byte_data(cl, 1);
> + break;
> + case 0x53: /* HYST */
> + res = swab16(i2c_smbus_read_word_data(cl, 2));
> + break;
> + case 0x55: /* OVER */
> + default:
> + res = swab16(i2c_smbus_read_word_data(cl, 3));
> + break;
> }
> - if (bank > 2)
> - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
> }
> - mutex_unlock(&data->lock);
> + if (bank > 2)
> + i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
> +
> return res;
> }
>
> static int
> -w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
> +w83781d_write_value_i2c(struct w83781d_data *data, u16 reg, u16 value)
> {
> struct i2c_client *client = &data->client;
> - int word_sized, bank;
> struct i2c_client *cl;
> + int bank;
>
> - mutex_lock(&data->lock);
> - if (!client->driver) { /* ISA device */
> - word_sized = (((reg & 0xff00) = 0x100)
> - || ((reg & 0xff00) = 0x200))
> - && (((reg & 0x00ff) = 0x53)
> - || ((reg & 0x00ff) = 0x55));
> - if (reg & 0xff00) {
> - outb_p(W83781D_REG_BANK,
> - client->addr + W83781D_ADDR_REG_OFFSET);
> - outb_p(reg >> 8,
> - client->addr + W83781D_DATA_REG_OFFSET);
> - }
> - outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
> - if (word_sized) {
> - outb_p(value >> 8,
> - client->addr + W83781D_DATA_REG_OFFSET);
> - outb_p((reg & 0xff) + 1,
> - client->addr + W83781D_ADDR_REG_OFFSET);
> - }
> - outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
> - if (reg & 0xff00) {
> - outb_p(W83781D_REG_BANK,
> - client->addr + W83781D_ADDR_REG_OFFSET);
> - outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
> - }
> + bank = (reg >> 8) & 0x0f;
> + if (bank > 2)
> + /* switch banks */
> + i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
> + bank);
> + if (bank = 0 || bank > 2) {
> + i2c_smbus_write_byte_data(client, reg & 0xff,
> + value & 0xff);
> } else {
> - bank = (reg >> 8) & 0x0f;
> - if (bank > 2)
> - /* switch banks */
> - i2c_smbus_write_byte_data(client, W83781D_REG_BANK,
> - bank);
> - if (bank = 0 || bank > 2) {
> - i2c_smbus_write_byte_data(client, reg & 0xff,
> - value & 0xff);
> - } else {
> - /* switch to subclient */
> - cl = data->lm75[bank - 1];
> - /* convert from ISA to LM75 I2C addresses */
> - switch (reg & 0xff) {
> - case 0x52: /* CONFIG */
> - i2c_smbus_write_byte_data(cl, 1, value & 0xff);
> - break;
> - case 0x53: /* HYST */
> - i2c_smbus_write_word_data(cl, 2, swab16(value));
> - break;
> - case 0x55: /* OVER */
> - i2c_smbus_write_word_data(cl, 3, swab16(value));
> - break;
> - }
> + /* switch to subclient */
> + cl = data->lm75[bank - 1];
> + /* convert from ISA to LM75 I2C addresses */
> + switch (reg & 0xff) {
> + case 0x52: /* CONFIG */
> + i2c_smbus_write_byte_data(cl, 1, value & 0xff);
> + break;
> + case 0x53: /* HYST */
> + i2c_smbus_write_word_data(cl, 2, swab16(value));
> + break;
> + case 0x55: /* OVER */
> + i2c_smbus_write_word_data(cl, 3, swab16(value));
> + break;
> }
> - if (bank > 2)
> - i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
> }
> - mutex_unlock(&data->lock);
> + if (bank > 2)
> + i2c_smbus_write_byte_data(client, W83781D_REG_BANK, 0);
> +
> return 0;
> }
>
> @@ -1815,6 +1608,255 @@ static struct w83781d_data *w83781d_upda
> return data;
> }
>
> +#ifdef CONFIG_ISA
> +
> +/* ISA device, if found */
> +static struct platform_device *pdev;
> +
> +static unsigned short isa_address = 0x290;
> +
> +/* I2C devices get this name attribute automatically, but for ISA devices
> + we must create it by ourselves. */
> +static ssize_t
> +show_name(struct device *dev, struct device_attribute *devattr, char *buf)
> +{
> + struct w83781d_data *data = dev_get_drvdata(dev);
> + return sprintf(buf, "%s\n", data->client.name);
> +}
> +static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
> +
> +static struct w83781d_data *w83781d_data_if_isa(void)
> +{
> + return pdev ? platform_get_drvdata(pdev) : NULL;
> +}
> +
> +/* Returns 1 if the I2C chip appears to be an alias of the ISA chip */
> +static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
> +{
> + struct w83781d_data *i2c, *isa;
> + int i;
> +
> + if (!pdev) /* No ISA chip */
> + return 0;
> +
> + i2c = i2c_get_clientdata(client);
> + isa = platform_get_drvdata(pdev);
> +
> + if (w83781d_read_value(isa, W83781D_REG_I2C_ADDR) != client->addr)
> + return 0; /* Address doesn't match */
> + if (w83781d_read_value(isa, W83781D_REG_WCHIPID) != chipid)
> + return 0; /* Chip type doesn't match */
> +
> + /* We compare all the limit registers, the config register and the
> + * interrupt mask registers */
> + for (i = 0x2b; i <= 0x3d; i++) {
> + if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
> + return 0;
> + }
> + if (w83781d_read_value(isa, W83781D_REG_CONFIG) !> + w83781d_read_value(i2c, W83781D_REG_CONFIG))
> + return 0;
> + for (i = 0x43; i <= 0x46; i++) {
> + if (w83781d_read_value(isa, i) != w83781d_read_value(i2c, i))
> + return 0;
> + }
> +
> + return 1;
> +}
> +
> +static int
> +w83781d_read_value_isa(struct w83781d_data *data, u16 reg)
> +{
> + struct i2c_client *client = &data->client;
> + int word_sized, res;
> +
> + word_sized = (((reg & 0xff00) = 0x100)
> + || ((reg & 0xff00) = 0x200))
> + && (((reg & 0x00ff) = 0x50)
> + || ((reg & 0x00ff) = 0x53)
> + || ((reg & 0x00ff) = 0x55));
> + if (reg & 0xff00) {
> + outb_p(W83781D_REG_BANK,
> + client->addr + W83781D_ADDR_REG_OFFSET);
> + outb_p(reg >> 8,
> + client->addr + W83781D_DATA_REG_OFFSET);
> + }
> + outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
> + res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
> + if (word_sized) {
> + outb_p((reg & 0xff) + 1,
> + client->addr + W83781D_ADDR_REG_OFFSET);
> + res > + (res << 8) + inb_p(client->addr +
> + W83781D_DATA_REG_OFFSET);
> + }
> + if (reg & 0xff00) {
> + outb_p(W83781D_REG_BANK,
> + client->addr + W83781D_ADDR_REG_OFFSET);
> + outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
> + }
> + return res;
> +}
> +
> +static void
> +w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value)
> +{
> + struct i2c_client *client = &data->client;
> + int word_sized;
> +
> + word_sized = (((reg & 0xff00) = 0x100)
> + || ((reg & 0xff00) = 0x200))
> + && (((reg & 0x00ff) = 0x53)
> + || ((reg & 0x00ff) = 0x55));
> + if (reg & 0xff00) {
> + outb_p(W83781D_REG_BANK,
> + client->addr + W83781D_ADDR_REG_OFFSET);
> + outb_p(reg >> 8,
> + client->addr + W83781D_DATA_REG_OFFSET);
> + }
> + outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
> + if (word_sized) {
> + outb_p(value >> 8,
> + client->addr + W83781D_DATA_REG_OFFSET);
> + outb_p((reg & 0xff) + 1,
> + client->addr + W83781D_ADDR_REG_OFFSET);
> + }
> + outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
> + if (reg & 0xff00) {
> + outb_p(W83781D_REG_BANK,
> + client->addr + W83781D_ADDR_REG_OFFSET);
> + outb_p(0, client->addr + W83781D_DATA_REG_OFFSET);
> + }
> +}
> +
> +/* The SMBus locks itself, usually, but nothing may access the Winbond between
> + 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.
> + There are some ugly typecasts here, but the good news is - they should
> + nowhere else be necessary! */
> +static int
> +w83781d_read_value(struct w83781d_data *data, u16 reg)
> +{
> + struct i2c_client *client = &data->client;
> + int res;
> +
> + mutex_lock(&data->lock);
> + if (client->driver)
> + res = w83781d_read_value_i2c(data, reg);
> + else
> + res = w83781d_read_value_isa(data, reg);
> + mutex_unlock(&data->lock);
> + return res;
> +}
> +
> +static int
> +w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
> +{
> + struct i2c_client *client = &data->client;
> +
> + mutex_lock(&data->lock);
> + if (client->driver)
> + w83781d_write_value_i2c(data, reg, value);
> + else
> + w83781d_write_value_isa(data, reg, value);
> + mutex_unlock(&data->lock);
> + return 0;
> +}
> +
> +static int __devinit
> +w83781d_isa_probe(struct platform_device *pdev)
> +{
> + int err, reg;
> + struct w83781d_data *data;
> + struct resource *res;
> + const char *name;
> +
> + /* Reserve the ISA region */
> + res = platform_get_resource(pdev, IORESOURCE_IO, 0);
> + if (!request_region(res->start + W83781D_ADDR_REG_OFFSET, 2,
> + "w83781d")) {
> + err = -EBUSY;
> + goto exit;
> + }
> +
> + data = kzalloc(sizeof(struct w83781d_data), GFP_KERNEL);
> + if (!data) {
> + err = -ENOMEM;
> + goto exit_release_region;
> + }
> + mutex_init(&data->lock);
> + data->client.addr = res->start;
> + i2c_set_clientdata(&data->client, data);
> + platform_set_drvdata(pdev, data);
> +
> + reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
> + switch (reg) {
> + case 0x30:
> + data->type = w83782d;
> + name = "w83782d";
> + break;
> + default:
> + data->type = w83781d;
> + name = "w83781d";
> + }
> + strlcpy(data->client.name, name, I2C_NAME_SIZE);
> +
> + /* Initialize the W83781D chip */
> + w83781d_init_device(&pdev->dev);
> +
> + /* Register sysfs hooks */
> + err = w83781d_create_files(&pdev->dev, data->type, 1);
> + if (err)
> + goto exit_remove_files;
> +
> + err = device_create_file(&pdev->dev, &dev_attr_name);
> + if (err)
> + goto exit_remove_files;
> +
> + data->hwmon_dev = hwmon_device_register(&pdev->dev);
> + if (IS_ERR(data->hwmon_dev)) {
> + err = PTR_ERR(data->hwmon_dev);
> + goto exit_remove_files;
> + }
> +
> + return 0;
> +
> + exit_remove_files:
> + 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);
> + kfree(data);
> + exit_release_region:
> + release_region(res->start + W83781D_ADDR_REG_OFFSET, 2);
> + exit:
> + return err;
> +}
> +
> +static int __devexit
> +w83781d_isa_remove(struct platform_device *pdev)
> +{
> + struct w83781d_data *data = platform_get_drvdata(pdev);
> +
> + hwmon_device_unregister(data->hwmon_dev);
> + 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_ADDR_REG_OFFSET, 2);
> + kfree(data);
> +
> + return 0;
> +}
> +
> +static struct platform_driver w83781d_isa_driver = {
> + .driver = {
> + .owner = THIS_MODULE,
> + .name = "w83781d",
> + },
> + .probe = w83781d_isa_probe,
> + .remove = w83781d_isa_remove,
Missing __devexit_p. Not your fault, the original code had the same
problem.
> +};
> +
> /* return 1 if a supported chip is found, 0 otherwise */
> static int __init
> w83781d_isa_found(unsigned short address)
> @@ -1951,12 +1993,10 @@ w83781d_isa_device_add(unsigned short ad
> }
>
> static int __init
> -sensors_w83781d_init(void)
> +w83781d_isa_register(void)
> {
> int res;
>
> - /* We register the ISA device first, so that we can skip the
> - * registration of an I2C interface to the same device. */
> if (w83781d_isa_found(isa_address)) {
> res = platform_driver_register(&w83781d_isa_driver);
> if (res)
> @@ -1968,16 +2008,89 @@ sensors_w83781d_init(void)
> goto exit_unreg_isa_driver;
> }
>
> + return 0;
> +
> +exit_unreg_isa_driver:
> + platform_driver_unregister(&w83781d_isa_driver);
> +exit:
> + return res;
> +
Extra blank line.
> +}
> +
> +static void __init
Should be __exit not __init.
> +w83781d_isa_unregister(void)
> +{
> + if (pdev) {
> + platform_device_unregister(pdev);
> + platform_driver_unregister(&w83781d_isa_driver);
> + }
> +}
> +#else /* !CONFIG_ISA */
> +
> +static struct w83781d_data *w83781d_data_if_isa(void)
> +{
> + return NULL;
> +}
> +
> +static int
> +w83781d_alias_detect(struct i2c_client *client, u8 chipid)
> +{
> + return 0;
> +}
> +
> +static int
> +w83781d_read_value(struct w83781d_data *data, u16 reg)
> +{
> + int res;
> +
> + mutex_lock(&data->lock);
> + res = w83781d_read_value_i2c(data, reg);
> + mutex_unlock(&data->lock);
> +
> + return res;
> +}
> +
> +static int
> +w83781d_write_value(struct w83781d_data *data, u16 reg, u16 value)
> +{
> + mutex_lock(&data->lock);
> + w83781d_write_value_i2c(data, reg, value);
> + mutex_unlock(&data->lock);
> +
> + return 0;
> +}
> +
> +static int __init
> +w83781d_isa_register(void)
> +{
> + return 0;
> +}
> +
> +static void __init
Should be __exit not __init.
> +w83781d_isa_unregister(void)
> +{
> +}
> +#endif /* CONFIG_ISA */
> +
> +static int __init
> +sensors_w83781d_init(void)
> +{
> + int res;
> +
> + /* We register the ISA device first, so that we can skip the
> + * registration of an I2C interface to the same device. */
> + res = w83781d_isa_register();
> + if (res)
> + goto exit;
> +
> res = i2c_add_driver(&w83781d_driver);
> if (res)
> - goto exit_unreg_isa_device;
> + goto exit_unreg_isa;
>
> return 0;
>
> - exit_unreg_isa_device:
> - platform_device_unregister(pdev);
> - exit_unreg_isa_driver:
> - platform_driver_unregister(&w83781d_isa_driver);
> + exit_unreg_isa:
> + w83781d_isa_unregister();
> exit:
> return res;
> }
> @@ -1985,10 +2098,7 @@ sensors_w83781d_init(void)
> static void __exit
> sensors_w83781d_exit(void)
> {
> - if (pdev) {
> - platform_device_unregister(pdev);
> - platform_driver_unregister(&w83781d_isa_driver);
> - }
> + w83781d_isa_unregister();
> i2c_del_driver(&w83781d_driver);
> }
>
In order to save some time, I've fixed all these minor issues myself.
Patch tested on my system with an ISA chip and it worked fine. I will
test later with a graphics adapter with a W83781D chip on the same
system.
--
Jean Delvare
_______________________________________________
lm-sensors mailing list
lm-sensors@lm-sensors.org
http://lists.lm-sensors.org/mailman/listinfo/lm-sensors
next prev parent reply other threads:[~2008-10-06 13:13 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-09-13 8:53 [lm-sensors] [PATCH 1/2] hwmon: w83781d: make ISA interface depend Wolfgang Grandegger
2008-10-06 13:13 ` Jean Delvare [this message]
2008-10-06 13:32 ` [lm-sensors] [PATCH 1/2] hwmon: w83781d: make ISA interface Wolfgang Grandegger
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20081006151352.7e73c909@hyperion.delvare \
--to=khali@linux-fr.org \
--cc=lm-sensors@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.