Skip to content

Commit

Permalink
hwmon: (w83781d) Stop abusing struct i2c_client for ISA devices
Browse files Browse the repository at this point in the history
Upcoming changes to the I2C part of the w83781d driver will cause ISA
devices to no longer have a struct i2c_client at hand. So, we must
stop (ab)using it now.

Signed-off-by: Jean Delvare <khali@linux-fr.org>
Cc: Wolfgang Grandegger <wg@grandegger.com>
  • Loading branch information
Jean Delvare authored and Jean Delvare committed Oct 17, 2008
1 parent 443850c commit 360782d
Showing 1 changed file with 26 additions and 37 deletions.
63 changes: 26 additions & 37 deletions drivers/hwmon/w83781d.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
Copyright (c) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
Philip Edelbrock <phil@netroedge.com>,
and Mark Studebaker <mdsxyz123@yahoo.com>
Copyright (c) 2007 Jean Delvare <khali@linux-fr.org>
Copyright (c) 2007 - 2008 Jean Delvare <khali@linux-fr.org>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -198,22 +198,16 @@ DIV_TO_REG(long val, enum chips type)
return i;
}

/* There are some complications in a module like this. First off, W83781D chips
may be both present on the SMBus and the ISA bus, and we have to handle
those cases separately at some places. Second, there might be several
W83781D chips available (well, actually, that is probably never done; but
it is a clean illustration of how to handle a case like that). Finally,
a specific chip may be attached to *both* ISA and SMBus, and we would
not like to detect it double. */

/* For ISA chips, we abuse the i2c_client addr and name fields. We also use
the driver field to differentiate between I2C and ISA chips. */
struct w83781d_data {
struct i2c_client client;
struct device *hwmon_dev;
struct mutex lock;
enum chips type;

/* For ISA device only */
const char *name;
int isa_addr;

struct mutex update_lock;
char valid; /* !=0 if following fields are valid */
unsigned long last_updated; /* In jiffies */
Expand Down Expand Up @@ -1625,7 +1619,7 @@ 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);
return sprintf(buf, "%s\n", data->name);
}
static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);

Expand Down Expand Up @@ -1671,7 +1665,6 @@ static int w83781d_alias_detect(struct i2c_client *client, u8 chipid)
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)
Expand All @@ -1681,31 +1674,30 @@ w83781d_read_value_isa(struct w83781d_data *data, u16 reg)
|| ((reg & 0x00ff) == 0x55));
if (reg & 0xff00) {
outb_p(W83781D_REG_BANK,
client->addr + W83781D_ADDR_REG_OFFSET);
data->isa_addr + W83781D_ADDR_REG_OFFSET);
outb_p(reg >> 8,
client->addr + W83781D_DATA_REG_OFFSET);
data->isa_addr + W83781D_DATA_REG_OFFSET);
}
outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
res = inb_p(client->addr + W83781D_DATA_REG_OFFSET);
outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET);
res = inb_p(data->isa_addr + W83781D_DATA_REG_OFFSET);
if (word_sized) {
outb_p((reg & 0xff) + 1,
client->addr + W83781D_ADDR_REG_OFFSET);
data->isa_addr + W83781D_ADDR_REG_OFFSET);
res =
(res << 8) + inb_p(client->addr +
(res << 8) + inb_p(data->isa_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);
data->isa_addr + W83781D_ADDR_REG_OFFSET);
outb_p(0, data->isa_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)
Expand All @@ -1714,22 +1706,22 @@ w83781d_write_value_isa(struct w83781d_data *data, u16 reg, u16 value)
|| ((reg & 0x00ff) == 0x55));
if (reg & 0xff00) {
outb_p(W83781D_REG_BANK,
client->addr + W83781D_ADDR_REG_OFFSET);
data->isa_addr + W83781D_ADDR_REG_OFFSET);
outb_p(reg >> 8,
client->addr + W83781D_DATA_REG_OFFSET);
data->isa_addr + W83781D_DATA_REG_OFFSET);
}
outb_p(reg & 0xff, client->addr + W83781D_ADDR_REG_OFFSET);
outb_p(reg & 0xff, data->isa_addr + W83781D_ADDR_REG_OFFSET);
if (word_sized) {
outb_p(value >> 8,
client->addr + W83781D_DATA_REG_OFFSET);
data->isa_addr + W83781D_DATA_REG_OFFSET);
outb_p((reg & 0xff) + 1,
client->addr + W83781D_ADDR_REG_OFFSET);
data->isa_addr + W83781D_ADDR_REG_OFFSET);
}
outb_p(value & 0xff, client->addr + W83781D_DATA_REG_OFFSET);
outb_p(value & 0xff, data->isa_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);
data->isa_addr + W83781D_ADDR_REG_OFFSET);
outb_p(0, data->isa_addr + W83781D_DATA_REG_OFFSET);
}
}

Expand Down Expand Up @@ -1774,7 +1766,6 @@ 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);
Expand All @@ -1790,21 +1781,19 @@ w83781d_isa_probe(struct platform_device *pdev)
goto exit_release_region;
}
mutex_init(&data->lock);
data->client.addr = res->start;
i2c_set_clientdata(&data->client, data);
data->isa_addr = res->start;
platform_set_drvdata(pdev, data);

reg = w83781d_read_value(data, W83781D_REG_WCHIPID);
switch (reg) {
case 0x30:
data->type = w83782d;
name = "w83782d";
data->name = "w83782d";
break;
default:
data->type = w83781d;
name = "w83781d";
data->name = "w83781d";
}
strlcpy(data->client.name, name, I2C_NAME_SIZE);

/* Initialize the W83781D chip */
w83781d_init_device(&pdev->dev);
Expand Down Expand Up @@ -1846,7 +1835,7 @@ 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_ADDR_REG_OFFSET, 2);
release_region(data->isa_addr + W83781D_ADDR_REG_OFFSET, 2);
kfree(data);

return 0;
Expand Down

0 comments on commit 360782d

Please sign in to comment.