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)
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
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 w83781d_data *data;
int err = 0;
const char *type_name = "";
int err;
const char *client_name = "";
int is_isa = i2c_is_isa_adapter(adapter);
enum vendor { winbond, asus } vendid;
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;
}
if (is_isa) {
if (!request_region(address, W83781D_EXTENT, "w83781d"))
if (is_isa)
if (!request_region(address, W83781D_EXTENT, "w83781d")) {
err = -EBUSY;
goto ERROR0;
release_region(address, W83781D_EXTENT);
}
}
/* Probe whether there is anything available on this address. Already
done for SMBus clients */
......@@ -1059,15 +1161,21 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
if (is_isa) {
#define REALLY_SLOW_IO
/* We need the timeouts for at least some LM78-like chips. But only
if we read 'undefined' registers. */
/* We need the timeouts for at least some LM78-like
chips. But only if we read 'undefined' registers. */
i = inb_p(address + 1);
if (inb_p(address + 2) != i)
goto ERROR0;
if (inb_p(address + 3) != i)
goto ERROR0;
if (inb_p(address + 7) != i)
goto ERROR0;
if (inb_p(address + 2) != i) {
err = -ENODEV;
goto ERROR1;
}
if (inb_p(address + 3) != i) {
err = -ENODEV;
goto ERROR1;
}
if (inb_p(address + 7) != i) {
err = -ENODEV;
goto ERROR1;
}
#undef REALLY_SLOW_IO
/* Let's just hope nothing breaks here */
......@@ -1075,7 +1183,8 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
outb_p(~i & 0x7f, address + 5);
if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
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)
if (!(new_client = kmalloc(sizeof (struct i2c_client) +
sizeof (struct w83781d_data), GFP_KERNEL))) {
err = -ENOMEM;
goto ERROR0;
goto ERROR1;
}
memset(new_client, 0x00, sizeof (struct i2c_client) +
......@@ -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
bank. */
if (kind < 0) {
if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80)
goto ERROR1;
if (w83781d_read_value(new_client, W83781D_REG_CONFIG) & 0x80){
err = -ENODEV;
goto ERROR2;
}
val1 = w83781d_read_value(new_client, W83781D_REG_BANK);
val2 = w83781d_read_value(new_client, W83781D_REG_CHIPMAN);
/* Check for Winbond or Asus ID if in bank 0 */
......@@ -1117,14 +1228,19 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
(((!(val1 & 0x80)) && (val2 != 0xa3) && (val2 != 0xc3)
&& (val2 != 0x94))
|| ((val1 & 0x80) && (val2 != 0x5c) && (val2 != 0x12)
&& (val2 != 0x06))))
goto ERROR1;
/* If Winbond SMBus, check address at 0x48. Asus doesn't support */
&& (val2 != 0x06)))) {
err = -ENODEV;
goto ERROR2;
}
/* If Winbond SMBus, check address at 0x48.
Asus doesn't support */
if ((!is_isa) && (((!(val1 & 0x80)) && (val2 == 0xa3)) ||
((val1 & 0x80) && (val2 == 0x5c)))) {
if (w83781d_read_value
(new_client, W83781D_REG_I2C_ADDR) != address)
goto ERROR1;
(new_client, W83781D_REG_I2C_ADDR) != address) {
err = -ENODEV;
goto ERROR2;
}
}
}
......@@ -1143,8 +1259,11 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
vendid = winbond;
else if ((val2 == 0x12) || (val2 == 0x06))
vendid = asus;
else
goto ERROR1;
else {
err = -ENODEV;
goto ERROR2;
}
/* mask off lower bit, not reliable */
val1 =
w83781d_read_value(new_client, W83781D_REG_WCHIPID) & 0xfe;
......@@ -1166,38 +1285,31 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
"Ignoring 'force' parameter for unknown chip at"
"adapter %d, address 0x%02x\n",
i2c_adapter_id(adapter), address);
goto ERROR1;
err = -EINVAL;
goto ERROR2;
}
}
if (kind == w83781d) {
type_name = "w83781d";
client_name = "W83781D chip";
} else if (kind == w83782d) {
type_name = "w83782d";
client_name = "W83782D chip";
} else if (kind == w83783s) {
type_name = "w83783s";
client_name = "W83783S chip";
} else if (kind == w83627hf) {
type_name = "w83627hf";
client_name = "W83627HF chip";
} else if (kind == as99127f) {
type_name = "as99127f";
client_name = "AS99127F chip";
} else if (kind == w83697hf) {
type_name = "w83697hf";
client_name = "W83697HF chip";
} else {
dev_err(&new_client->dev, "Internal error: unknown kind (%d)?!?", kind);
goto ERROR1;
dev_err(&new_client->dev, "Internal error: unknown "
"kind (%d)?!?", kind);
err = -ENODEV;
goto ERROR2;
}
/* Reserve the ISA region */
if (is_isa)
request_region(address, W83781D_EXTENT, type_name);
/* Fill in the remaining client fields and put it into the global list */
/* Fill in the remaining client fields and put into the global list */
strlcpy(new_client->dev.name, client_name, DEVICE_NAME_SIZE);
data->type = kind;
......@@ -1206,76 +1318,13 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
/* Tell the I2C layer a new client has arrived */
if ((err = i2c_attach_client(new_client)))
goto ERROR3;
goto ERROR2;
/* attach secondary i2c lm75-like clients */
if (!is_isa) {
if (!(data->lm75 = kmalloc(2 * sizeof (struct i2c_client),
GFP_KERNEL))) {
err = -ENOMEM;
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;
}
if ((err = w83781d_detect_subclients(adapter, address,
kind, new_client)))
goto ERROR3;
} else {
data->lm75 = NULL;
}
......@@ -1346,24 +1395,14 @@ w83781d_detect(struct i2c_adapter *adapter, int address, int kind)
w83781d_init_client(new_client);
return 0;
/* OK, this is not exactly good programming practice, usually. But it is
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:
ERROR3:
i2c_detach_client(new_client);
ERROR3:
ERROR2:
kfree(new_client);
ERROR1:
if (is_isa)
release_region(address, W83781D_EXTENT);
ERROR1:
kfree(new_client);
ERROR0:
ERROR0:
return err;
}
......@@ -1373,12 +1412,7 @@ w83781d_detach_client(struct i2c_client *client)
struct w83781d_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");
return err;
}
/* release ISA region or I2C subclients first */
if (i2c_is_isa_client(client)) {
release_region(client->addr, W83781D_EXTENT);
} else {
......@@ -1387,6 +1421,14 @@ w83781d_detach_client(struct i2c_client *client)
i2c_detach_client(&data->lm75[1]);
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);
return 0;
......
......@@ -124,7 +124,7 @@ int i2c_add_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_client *client;
int res = 0;
......@@ -144,7 +144,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
/* detach any active clients. This must be done first, because
* 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);
/* detaching devices is unconditional of the set notify
......@@ -215,8 +215,7 @@ int i2c_add_driver(struct i2c_driver *driver)
int i2c_del_driver(struct i2c_driver *driver)
{
struct list_head *item1;
struct list_head *item2;
struct list_head *item1, *item2, *_n;
struct i2c_client *client;
struct i2c_adapter *adap;
......@@ -245,7 +244,7 @@ int i2c_del_driver(struct i2c_driver *driver)
goto out_unlock;
}
} else {
list_for_each(item2,&adap->clients) {
list_for_each_safe(item2, _n, &adap->clients) {
client = list_entry(item2, struct i2c_client, list);
if (client->driver != driver)
continue;
......
......@@ -98,6 +98,7 @@
#define I2C_DRIVERID_ZR36120 50 /* Zoran 36120 video encoder */
#define I2C_DRIVERID_24LC32A 51 /* Microchip 24LC32A 32k EEPROM */
#define I2C_DRIVERID_STM41T00 52 /* real time clock */
#define I2C_DRIVERID_UDA1342 53 /* UDA1342 audio codec */
......@@ -178,6 +179,7 @@
#define I2C_ALGO_MPC8XX 0x110000 /* MPC8xx PowerPC 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_OCP_IOP3XX 0x140000 /* XSCALE IOP3XX On-chip I2C alg */
#define I2C_ALGO_EXP 0x800000 /* experimental */
......@@ -213,6 +215,9 @@
#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_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 */
#define I2C_HW_P_LP 0x00 /* Parallel port interface */
......@@ -234,6 +239,8 @@
/* --- PowerPC on-chip adapters */
#define I2C_HW_OCP 0x00 /* IBM on-chip I2C adapter */
/* --- XSCALE on-chip adapters */
#define I2C_HW_IOP321 0x00
/* --- SMBus only adapters */
#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