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
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 */
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);
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 & 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)
|| ((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);
}
}
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);
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);
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;