Commit bc1f1afe authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/i2c-2.5

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 3ac7f581 31f68121
...@@ -1031,27 +1031,129 @@ w83781d_attach_adapter(struct i2c_adapter *adapter) ...@@ -1031,27 +1031,129 @@ w83781d_attach_adapter(struct i2c_adapter *adapter)
return i2c_detect(adapter, &addr_data, w83781d_detect); return i2c_detect(adapter, &addr_data, w83781d_detect);
} }
/* Assumes that adapter is of I2C, not ISA variety.
* OTHERWISE DON'T CALL THIS
*/
static int
w83781d_detect_subclients(struct i2c_adapter *adapter, int address, int kind,
struct i2c_client *new_client)
{
int i, val1 = 0, id;
int err;
const char *client_name;
struct w83781d_data *data = i2c_get_clientdata(new_client);
if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client),
GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR_SC_0;
}
memset(data->lm75, 0x00, 2 * sizeof (struct i2c_client));
id = i2c_adapter_id(adapter);
if (force_subclients[0] == id && force_subclients[1] == address) {
for (i = 2; i <= 3; i++) {
if (force_subclients[i] < 0x48 ||
force_subclients[i] > 0x4f) {
dev_err(&new_client->dev, "Invalid subclient "
"address %d; must be 0x48-0x4f\n",
force_subclients[i]);
err = -EINVAL;
goto ERROR_SC_1;
}
}
w83781d_write_value(new_client, W83781D_REG_I2C_SUBADDR,
(force_subclients[2] & 0x07) |
((force_subclients[3] & 0x07) << 4));
data->lm75[0].addr = force_subclients[2];
} else {
val1 = w83781d_read_value(new_client, W83781D_REG_I2C_SUBADDR);
data->lm75[0].addr = 0x48 + (val1 & 0x07);
}
if (kind != w83783s) {
if (force_subclients[0] == id &&
force_subclients[1] == address) {
data->lm75[1].addr = force_subclients[3];
} else {
data->lm75[1].addr = 0x48 + ((val1 >> 4) & 0x07);
}
if (data->lm75[0].addr == data->lm75[1].addr) {
dev_err(&new_client->dev,
"Duplicate addresses 0x%x for subclients.\n",
data->lm75[0].addr);
err = -EBUSY;
goto ERROR_SC_1;
}
}
if (kind == w83781d)
client_name = "W83781D subclient";
else if (kind == w83782d)
client_name = "W83782D subclient";
else if (kind == w83783s)
client_name = "W83783S subclient";
else if (kind == w83627hf)
client_name = "W83627HF subclient";
else if (kind == as99127f)
client_name = "AS99127F subclient";
else
client_name = "unknown subclient?";
for (i = 0; i <= 1; i++) {
/* store all data in w83781d */
i2c_set_clientdata(&data->lm75[i], NULL);
data->lm75[i].adapter = adapter;
data->lm75[i].driver = &w83781d_driver;
data->lm75[i].flags = 0;
strlcpy(data->lm75[i].dev.name, client_name,
DEVICE_NAME_SIZE);
if ((err = i2c_attach_client(&(data->lm75[i])))) {
dev_err(&new_client->dev, "Subclient %d "
"registration at address 0x%x "
"failed.\n", i, data->lm75[i].addr);
if (i == 1)
goto ERROR_SC_2;
goto ERROR_SC_1;
}
if (kind == w83783s)
break;
}
return 0;
/* Undo inits in case of errors */
ERROR_SC_2:
i2c_detach_client(&(data->lm75[0]));
ERROR_SC_1:
kfree(data->lm75);
ERROR_SC_0:
return err;
}
static int static int
w83781d_detect(struct i2c_adapter *adapter, int address, int kind) w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
{ {
int i = 0, val1 = 0, val2, id; int i = 0, val1 = 0, val2;
struct i2c_client *new_client; struct i2c_client *new_client;
struct w83781d_data *data; struct w83781d_data *data;
int err = 0; int err;
const char *type_name = "";
const char *client_name = ""; const char *client_name = "";
int is_isa = i2c_is_isa_adapter(adapter); int is_isa = i2c_is_isa_adapter(adapter);
enum vendor { winbond, asus } vendid; enum vendor { winbond, asus } vendid;
if (!is_isa if (!is_isa
&& !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
err = -EINVAL;
goto ERROR0; goto ERROR0;
}
if (is_isa) { if (is_isa)
if (!request_region(address, W83781D_EXTENT, "w83781d")) if (!request_region(address, W83781D_EXTENT, "w83781d")) {
err = -EBUSY;
goto ERROR0; goto ERROR0;
release_region(address, W83781D_EXTENT); }
}
/* Probe whether there is anything available on this address. Already /* Probe whether there is anything available on this address. Already
done for SMBus clients */ done for SMBus clients */
...@@ -1059,15 +1161,21 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1059,15 +1161,21 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa) { if (is_isa) {
#define REALLY_SLOW_IO #define REALLY_SLOW_IO
/* We need the timeouts for at least some LM78-like chips. But only /* We need the timeouts for at least some LM78-like
if we read 'undefined' registers. */ chips. But only if we read 'undefined' registers. */
i = inb_p(address + 1); i = inb_p(address + 1);
if (inb_p(address + 2) != i) if (inb_p(address + 2) != i) {
goto ERROR0; err = -ENODEV;
if (inb_p(address + 3) != i) goto ERROR1;
goto ERROR0; }
if (inb_p(address + 7) != i) if (inb_p(address + 3) != i) {
goto ERROR0; err = -ENODEV;
goto ERROR1;
}
if (inb_p(address + 7) != i) {
err = -ENODEV;
goto ERROR1;
}
#undef REALLY_SLOW_IO #undef REALLY_SLOW_IO
/* Let's just hope nothing breaks here */ /* Let's just hope nothing breaks here */
...@@ -1075,7 +1183,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1075,7 +1183,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
outb_p(~i & 0x7f, address + 5); outb_p(~i & 0x7f, address + 5);
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) { if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
outb_p(i, address + 5); outb_p(i, address + 5);
return 0; err = -ENODEV;
goto ERROR1;
} }
} }
} }
...@@ -1087,7 +1196,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1087,7 +1196,7 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (!(new_client = kmalloc(sizeof (struct i2c_client) + if (!(new_client = kmalloc(sizeof (struct i2c_client) +
sizeof (struct w83781d_data), GFP_KERNEL))) { sizeof (struct w83781d_data), GFP_KERNEL))) {
err = -ENOMEM; err = -ENOMEM;
goto ERROR0; goto ERROR1;
} }
memset(new_client, 0x00, sizeof (struct i2c_client) + memset(new_client, 0x00, sizeof (struct i2c_client) +
...@@ -1108,8 +1217,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1108,8 +1217,10 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
force_*=... parameter, and the Winbond will be reset to the right force_*=... parameter, and the Winbond will be reset to the right
bank. */ bank. */
if (kind < 0) { if (kind < 0) {
if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80) if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80){
goto ERROR1; err = -ENODEV;
goto ERROR2;
}
val1 = w83781d_read_value(new_client, W83781D_REG_BANK); val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN); val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
/* Check for Winbond or Asus ID if in bank 0 */ /* Check for Winbond or Asus ID if in bank 0 */
...@@ -1117,14 +1228,19 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1117,14 +1228,19 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3) (((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)
&& (val2 != 0x94)) && (val2 != 0x94))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12) || ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)
&& (val2 != 0x06)))) && (val2 != 0x06)))) {
goto ERROR1; err = -ENODEV;
/* If Winbond SMBus, check address at 0x48. Asus doesn't support */ goto ERROR2;
}
/* If Winbond SMBus, check address at 0x48.
Asus doesn't support */
if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) || if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
((val1 & 0x80) && (val2 == 0x5c)))) { ((val1 & 0x80) && (val2 == 0x5c)))) {
if (w83781d_read_value if (w83781d_read_value
(new_client, W83781D_REG_I2C_ADDR) != address) (new_client, W83781D_REG_I2C_ADDR) != address) {
goto ERROR1; err = -ENODEV;
goto ERROR2;
}
} }
} }
...@@ -1143,8 +1259,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1143,8 +1259,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
vendid = winbond; vendid = winbond;
else if ((val2 == 0x12) || (val2 == 0x06)) else if ((val2 == 0x12) || (val2 == 0x06))
vendid = asus; vendid = asus;
else else {
goto ERROR1; err = -ENODEV;
goto ERROR2;
}
/* mask off lower bit, not reliable */ /* mask off lower bit, not reliable */
val1 = val1 =
w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe; w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe;
...@@ -1166,38 +1285,31 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1166,38 +1285,31 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
"Ignoring 'force' parameter for unknown chip at" "Ignoring 'force' parameter for unknown chip at"
"adapter %d, address 0x%02x\n", "adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address); i2c_adapter_id(adapter), address);
goto ERROR1; err = -EINVAL;
goto ERROR2;
} }
} }
if (kind == w83781d) { if (kind == w83781d) {
type_name = "w83781d";
client_name = "W83781D chip"; client_name = "W83781D chip";
} else if (kind == w83782d) { } else if (kind == w83782d) {
type_name = "w83782d";
client_name = "W83782D chip"; client_name = "W83782D chip";
} else if (kind == w83783s) { } else if (kind == w83783s) {
type_name = "w83783s";
client_name = "W83783S chip"; client_name = "W83783S chip";
} else if (kind == w83627hf) { } else if (kind == w83627hf) {
type_name = "w83627hf";
client_name = "W83627HF chip"; client_name = "W83627HF chip";
} else if (kind == as99127f) { } else if (kind == as99127f) {
type_name = "as99127f";
client_name = "AS99127F chip"; client_name = "AS99127F chip";
} else if (kind == w83697hf) { } else if (kind == w83697hf) {
type_name = "w83697hf";
client_name = "W83697HF chip"; client_name = "W83697HF chip";
} else { } else {
dev_err(&new_client->dev, "Internal error: unknown kind (%d)?!?", kind); dev_err(&new_client->dev, "Internal error: unknown "
goto ERROR1; "kind (%d)?!?", kind);
err = -ENODEV;
goto ERROR2;
} }
/* Reserve the ISA region */ /* Fill in the remaining client fields and put into the global list */
if (is_isa)
request_region(address, W83781D_EXTENT, type_name);
/* Fill in the remaining client fields and put it into the global list */
strlcpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE); strlcpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
data->type = kind; data->type = kind;
...@@ -1206,76 +1318,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1206,76 +1318,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
/* Tell the I2C layer a new client has arrived */ /* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client))) if ((err = i2c_attach_client(new_client)))
goto ERROR3; goto ERROR2;
/* attach secondary i2c lm75-like clients */ /* attach secondary i2c lm75-like clients */
if (!is_isa) { if (!is_isa) {
if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client), if ((err = w83781d_detect_subclients(adapter, address,
GFP_KERNEL))) { kind, new_client)))
err = -ENOMEM; goto ERROR3;
goto ERROR4;
}
memset(data->lm75, 0x00, 2 * sizeof (struct i2c_client));
id = i2c_adapter_id(adapter);
if (force_subclients[0] == id && force_subclients[1] == address) {
for (i = 2; i <= 3; i++) {
if (force_subclients[i] < 0x48 ||
force_subclients[i] > 0x4f) {
dev_err(&new_client->dev,
"Invalid subclient address %d; must be 0x48-0x4f\n",
force_subclients[i]);
goto ERROR5;
}
}
w83781d_write_value(new_client,
W83781D_REG_I2C_SUBADDR,
(force_subclients[2] & 0x07) |
((force_subclients[3] & 0x07) <<
4));
data->lm75[0].addr = force_subclients[2];
} else {
val1 = w83781d_read_value(new_client,
W83781D_REG_I2C_SUBADDR);
data->lm75[0].addr = 0x48 + (val1 & 0x07);
}
if (kind != w83783s) {
if (force_subclients[0] == id &&
force_subclients[1] == address) {
data->lm75[1].addr = force_subclients[3];
} else {
data->lm75[1].addr =
0x48 + ((val1 >> 4) & 0x07);
}
if (data->lm75[0].addr == data->lm75[1].addr) {
dev_err(&new_client->dev,
"Duplicate addresses 0x%x for subclients.\n",
data->lm75[0].addr);
goto ERROR5;
}
}
if (kind == w83781d)
client_name = "W83781D subclient";
else if (kind == w83782d)
client_name = "W83782D subclient";
else if (kind == w83783s)
client_name = "W83783S subclient";
else if (kind == w83627hf)
client_name = "W83627HF subclient";
else if (kind == as99127f)
client_name = "AS99127F subclient";
for (i = 0; i <= 1; i++) {
i2c_set_clientdata(&data->lm75[i], NULL); /* store all data in w83781d */
data->lm75[i].adapter = adapter;
data->lm75[i].driver = &w83781d_driver;
data->lm75[i].flags = 0;
strlcpy(data->lm75[i].dev.name, client_name,
DEVICE_NAME_SIZE);
if (kind == w83783s)
break;
}
} else { } else {
data->lm75 = NULL; data->lm75 = NULL;
} }
...@@ -1346,24 +1395,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind) ...@@ -1346,24 +1395,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
w83781d_init_client(new_client); w83781d_init_client(new_client);
return 0; return 0;
/* OK, this is not exactly good programming practice, usually. But it is ERROR3:
very code-efficient in this case. */
ERROR5:
if (!is_isa) {
i2c_detach_client(&data->lm75[0]);
if (data->type != w83783s)
i2c_detach_client(&data->lm75[1]);
kfree(data->lm75);
}
ERROR4:
i2c_detach_client(new_client); i2c_detach_client(new_client);
ERROR3: ERROR2:
kfree(new_client);
ERROR1:
if (is_isa) if (is_isa)
release_region(address, W83781D_EXTENT); release_region(address, W83781D_EXTENT);
ERROR1: ERROR0:
kfree(new_client);
ERROR0:
return err; return err;
} }
...@@ -1373,12 +1412,7 @@ w83781d_detach_client(struct i2c_client *client) ...@@ -1373,12 +1412,7 @@ w83781d_detach_client(struct i2c_client *client)
struct w83781d_data *data = i2c_get_clientdata(client); struct w83781d_data *data = i2c_get_clientdata(client);
int err; int err;
if ((err = i2c_detach_client(client))) { /* release ISA region or I2C subclients first */
dev_err(&client->dev,
"Client deregistration failed, client not detached.\n");
return err;
}
if (i2c_is_isa_client(client)) { if (i2c_is_isa_client(client)) {
release_region(client->addr, W83781D_EXTENT); release_region(client->addr, W83781D_EXTENT);
} else { } else {
...@@ -1387,6 +1421,14 @@ w83781d_detach_client(struct i2c_client *client) ...@@ -1387,6 +1421,14 @@ w83781d_detach_client(struct i2c_client *client)
i2c_detach_client(&data->lm75[1]); i2c_detach_client(&data->lm75[1]);
kfree(data->lm75); kfree(data->lm75);
} }
/* now it's safe to scrap the rest */
if ((err = i2c_detach_client(client))) {
dev_err(&client->dev,
"Client deregistration failed, client not detached.\n");
return err;
}
kfree(client); kfree(client);
return 0; return 0;
......
...@@ -124,7 +124,7 @@ int i2c_add_adapter(struct i2c_adapter *adap) ...@@ -124,7 +124,7 @@ int i2c_add_adapter(struct i2c_adapter *adap)
int i2c_del_adapter(struct i2c_adapter *adap) int i2c_del_adapter(struct i2c_adapter *adap)
{ {
struct list_head *item; struct list_head *item, *_n;
struct i2c_driver *driver; struct i2c_driver *driver;
struct i2c_client *client; struct i2c_client *client;
int res = 0; int res = 0;
...@@ -144,7 +144,7 @@ int i2c_del_adapter(struct i2c_adapter *adap) ...@@ -144,7 +144,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because /* detach any active clients. This must be done first, because
* it can fail; in which case we give upp. */ * it can fail; in which case we give upp. */
list_for_each(item,&adap->clients) { list_for_each_safe(item, _n, &adap->clients) {
client = list_entry(item, struct i2c_client, list); client = list_entry(item, struct i2c_client, list);
/* detaching devices is unconditional of the set notify /* detaching devices is unconditional of the set notify
...@@ -215,8 +215,7 @@ int i2c_add_driver(struct i2c_driver *driver) ...@@ -215,8 +215,7 @@ int i2c_add_driver(struct i2c_driver *driver)
int i2c_del_driver(struct i2c_driver *driver) int i2c_del_driver(struct i2c_driver *driver)
{ {
struct list_head *item1; struct list_head *item1, *item2, *_n;
struct list_head *item2;
struct i2c_client *client; struct i2c_client *client;
struct i2c_adapter *adap; struct i2c_adapter *adap;
...@@ -245,7 +244,7 @@ int i2c_del_driver(struct i2c_driver *driver) ...@@ -245,7 +244,7 @@ int i2c_del_driver(struct i2c_driver *driver)
goto out_unlock; goto out_unlock;
} }
} else { } else {
list_for_each(item2,&adap->clients) { list_for_each_safe(item2, _n, &adap->clients) {
client = list_entry(item2, struct i2c_client, list); client = list_entry(item2, struct i2c_client, list);
if (client->driver != driver) if (client->driver != driver)
continue; continue;
......
...@@ -98,6 +98,7 @@ ...@@ -98,6 +98,7 @@
#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */ #define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */ #define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
#define I2C_DRIVERID_STM41T00 52 /* real time clock */ #define I2C_DRIVERID_STM41T00 52 /* real time clock */
#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */
...@@ -178,6 +179,7 @@ ...@@ -178,6 +179,7 @@
#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */ #define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC I2C algorithm */
#define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */ #define I2C_ALGO_OCP 0x120000 /* IBM or otherwise On-chip I2C algorithm */
#define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */ #define I2C_ALGO_BITHS 0x130000 /* enhanced bit style adapters */
#define I2C_ALGO_OCP_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
#define I2C_ALGO_EXP 0x800000 /* experimental */ #define I2C_ALGO_EXP 0x800000 /* experimental */
...@@ -213,6 +215,9 @@ ...@@ -213,6 +215,9 @@
#define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */ #define I2C_HW_B_FRODO 0x13 /* 2d3D, Inc. SA-1110 Development Board */
#define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface (ARM) */ #define I2C_HW_B_OMAHA 0x14 /* Omaha I2C interface (ARM) */
#define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */ #define I2C_HW_B_GUIDE 0x15 /* Guide bit-basher */
#define I2C_HW_B_IXP2000 0x16 /* GPIO on IXP2000 systems */
#define I2C_HW_B_IXP425 0x17 /* GPIO on IXP425 systems */
#define I2C_HW_B_S3VIA 0x18 /* S3Via ProSavage adapter */
/* --- PCF 8584 based algorithms */ /* --- PCF 8584 based algorithms */
#define I2C_HW_P_LP 0x00 /* Parallel port interface */ #define I2C_HW_P_LP 0x00 /* Parallel port interface */
...@@ -234,6 +239,8 @@ ...@@ -234,6 +239,8 @@
/* --- PowerPC on-chip adapters */ /* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */ #define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
/* --- XSCALE on-chip adapters */
#define I2C_HW_IOP321 0x00
/* --- SMBus only adapters */ /* --- SMBus only adapters */
#define I2C_HW_SMBUS_PIIX4 0x00 #define I2C_HW_SMBUS_PIIX4 0x00
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment